javauis/mmapi_qt/baseline/src.dsa/cmmavideoplayer.cpp
branchRCL_3
changeset 17 0fd27995241b
equal deleted inserted replaced
15:f9bb0fca356a 17:0fd27995241b
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class is used for playing video.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 //  INCLUDE FILES
       
    20 #include <mmf/server/mmffile.h>
       
    21 #include <logger.h>
       
    22 
       
    23 #include "cmmavideoplayer.h"
       
    24 #include "mmmadisplay.h"
       
    25 #include "mmafunctionserver.h"
       
    26 #include "cmmadsawindow.h"
       
    27 
       
    28 // CONSTANTS
       
    29 _LIT(KVideoControlName, "VideoControl");
       
    30 
       
    31 CMMAVideoPlayer* CMMAVideoPlayer::NewLC(
       
    32     CMMAMMFResolver* aResolver)
       
    33 {
       
    34     CMMAVideoPlayer* self =
       
    35         new(ELeave) CMMAVideoPlayer(aResolver);
       
    36     CleanupStack::PushL(self);
       
    37     self->ConstructL();
       
    38     return self;
       
    39 }
       
    40 
       
    41 CMMAVideoPlayer::~CMMAVideoPlayer()
       
    42 {
       
    43     LOG( EJavaMMAPI, EInfo, "MMA::CMMAVideoPlayer::~CMMAVideoPlayer");
       
    44     if (iDisplay)
       
    45     {
       
    46         TRAPD(err, iDisplay->SetWindowL(NULL));
       
    47         if (err != KErrNone)
       
    48         {
       
    49             __ASSERT_DEBUG(EFalse, User::Invariant());
       
    50         }
       
    51     }
       
    52     delete iDSAWindow;
       
    53     delete iEmptySnapshotImage;
       
    54     delete iActiveSchedulerWait;
       
    55 }
       
    56 
       
    57 CMMAVideoPlayer::CMMAVideoPlayer(
       
    58     CMMAMMFResolver* aResolver):
       
    59         CMMAAudioPlayer(aResolver),
       
    60         iVideoControllerCustomCommands(iController),
       
    61         iVideoPlayControllerCustomCommands(iController)
       
    62 {
       
    63 }
       
    64 
       
    65 void CMMAVideoPlayer::ConstructL()
       
    66 {
       
    67     CMMAAudioPlayer::ConstructL();
       
    68     iActiveSchedulerWait = new(ELeave)CActiveSchedulerWait;
       
    69 }
       
    70 
       
    71 EXPORT_C void CMMAVideoPlayer::SetPlayerListenerObjectL(jobject aListenerObject,
       
    72         JNIEnv* aJni,
       
    73         MMMAEventPoster* aEventPoster)
       
    74 {
       
    75     CMMAPlayer::SetPlayerListenerObjectL(aListenerObject,
       
    76                                          aJni,
       
    77                                          aEventPoster);
       
    78 
       
    79     // this method must be called only ones
       
    80     __ASSERT_DEBUG(!iDSAWindow, User::Invariant());
       
    81 
       
    82     // create window for videoplayer
       
    83     // event poster is always MMAFunctionServer type.
       
    84 
       
    85     iDSAWindow = CMMADSAWindow::NewL(
       
    86                      static_cast< MMAFunctionServer* >(iEventPoster),
       
    87                      this,
       
    88                      &iVideoPlayControllerCustomCommands);
       
    89 }
       
    90 
       
    91 EXPORT_C void CMMAVideoPlayer::SetDisplayL(MMMADisplay* aDisplay)
       
    92 {
       
    93     // now it is ready to draw
       
    94     iDisplay = aDisplay;
       
    95     iDisplay->SetWindowL(iDSAWindow);
       
    96 
       
    97     // if state < prefeteched then we dont know actual source size yet
       
    98     // and it will be set after prefetch
       
    99     if (iState >= EPrefetched)
       
   100     {
       
   101         SourceSizeChanged();
       
   102     }
       
   103 }
       
   104 void CMMAVideoPlayer::RealizeL()
       
   105 {
       
   106     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::RealizeL");
       
   107     // DataSource must have at least 1 stream or
       
   108     // we must have file to play
       
   109     if ((iSourceStreams.Count() == 0) && !iFileName)
       
   110     {
       
   111         User::Leave(KErrNotEnoughStreams);
       
   112     }
       
   113 
       
   114     // If file locator is used, then file is prefetched
       
   115     // in realized state so that FramePositioningControl
       
   116     // can acquire frame count in REALIZED state
       
   117     if (iFileName)
       
   118     {
       
   119         PrefetchFileL();
       
   120         if (!iActiveSchedulerWait->IsStarted())
       
   121         {
       
   122             iActiveSchedulerWait->Start();
       
   123         }
       
   124         // If the player has not changed state during wait,
       
   125         // Then there is an error condition.
       
   126         if (iState != ERealized)
       
   127         {
       
   128             User::Leave(KErrNotSupported);
       
   129         }
       
   130     }
       
   131     else
       
   132     {
       
   133         CMMAPlayer::RealizeL();
       
   134     }
       
   135 }
       
   136 
       
   137 void CMMAVideoPlayer::PrefetchL()
       
   138 {
       
   139     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::PrefetchL");
       
   140     if (iFileName)
       
   141     {
       
   142         // File has already been prefetched when realizing
       
   143 
       
   144         // If initDisplayMode was called before prefetch,
       
   145         // then the display must notified about source size.
       
   146         if (iDisplay)
       
   147         {
       
   148             SourceSizeChanged();
       
   149         }
       
   150 
       
   151         ChangeState(EPrefetched);
       
   152         PostActionCompleted(KErrNone);
       
   153     }
       
   154     else
       
   155     {
       
   156         // Using TDes -- load the whole video
       
   157         iSourceStreams[ 0 ]->ReadAllL();
       
   158     }
       
   159     // CMMASourceStream will notify with ReadCompleted
       
   160 }
       
   161 
       
   162 EXPORT_C void CMMAVideoPlayer::ReadCompletedL(TInt aStatus, const TDesC8& aData)
       
   163 {
       
   164     LOG1( EJavaMMAPI, EInfo, "CMMAVideoPlayer::ReadCompletedL: status = %d", aStatus);
       
   165     if (aStatus < KErrNone)
       
   166     {
       
   167         PostActionCompleted(aStatus);
       
   168     }
       
   169     else
       
   170     {
       
   171         TRAPD(err, PrefetchDataL(aData));
       
   172         if (err != KErrNone)
       
   173         {
       
   174             PostActionCompleted(err);
       
   175         }
       
   176         // action completed event will be delivered from handleEvent
       
   177     }
       
   178 }
       
   179 
       
   180 void CMMAVideoPlayer::HandleEvent(const TMMFEvent& aEvent)
       
   181 {
       
   182     LOG1( EJavaMMAPI, EInfo, "MMA:CMMAVideoPlayer::HandleEvent %d", aEvent.iEventType.iUid);
       
   183 
       
   184     // KNotCompleteVideoError can be notified when video is not complete
       
   185     // ( missing sound ) but still can be played. Because
       
   186     // CMMAAudioPlayer::HandleEvent fails with all negative error codes,
       
   187     // do not call it with KNotCompleteVideoError error when preparing.
       
   188     if ((aEvent.iErrorCode != KNotCompleteVideoError) ||
       
   189             (aEvent.iEventType != KMMFEventCategoryVideoPrepareComplete))
       
   190     {
       
   191         CMMAAudioPlayer::HandleEvent(aEvent);
       
   192     }
       
   193 
       
   194     // video opened, preparing
       
   195     if (aEvent.iEventType == KMMFEventCategoryVideoOpenComplete)
       
   196     {
       
   197         if (aEvent.iErrorCode == KErrNone)
       
   198         {
       
   199             TInt prepareError(iVideoPlayControllerCustomCommands.Prepare());
       
   200             if (prepareError != KErrNone)
       
   201             {
       
   202                 // opening failed, notifying java
       
   203                 PostActionCompleted(prepareError);
       
   204             }
       
   205         }
       
   206         else
       
   207         {
       
   208             // opening failed, notifying java
       
   209             PostActionCompleted(aEvent.iErrorCode);
       
   210         }
       
   211     }
       
   212     // final state of prefetch ( prepare completed )
       
   213     else if (aEvent.iEventType == KMMFEventCategoryVideoPrepareComplete)
       
   214     {
       
   215         // This callback must be handled differently depending on whether
       
   216         // player is created for a file locator or for a stream. When file
       
   217         // locator is used, this callback is made in realized state. For
       
   218         // stream it is made in prefetched state.
       
   219         PrepareDisplay();
       
   220         if (iFileName)
       
   221         {
       
   222             LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::HandleEvent: Using filename, change state to REALIZED");
       
   223 
       
   224             // If there is an error condition, then the player state is not
       
   225             // changed, which indicates the error condition to StartL when
       
   226             // the ActiveSchedulerWait returns. KNotCompleteVideoError is not
       
   227             // considered as an error condition, instead it indicates that some
       
   228             // elements of the media cannot be played (e.g. video OR audio)
       
   229             if (aEvent.iErrorCode == KErrNone ||
       
   230                     aEvent.iErrorCode == KNotCompleteVideoError)
       
   231             {
       
   232                 ChangeState(ERealized);
       
   233             }
       
   234             __ASSERT_DEBUG(iActiveSchedulerWait->IsStarted(), User::Invariant());
       
   235             iActiveSchedulerWait->AsyncStop();
       
   236         }
       
   237         else
       
   238         {
       
   239             LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::HandleEvent: Not using filename, change state to PREFETCHED");
       
   240             CompletePrefetch(aEvent.iErrorCode);
       
   241         }
       
   242     }
       
   243     else            // in case of any other event
       
   244     {
       
   245         if (aEvent.iErrorCode != KErrNone)
       
   246         {
       
   247             PostActionCompleted(aEvent.iErrorCode);   //some other error
       
   248         }
       
   249     }
       
   250 }
       
   251 
       
   252 void CMMAVideoPlayer::CompletePrefetch(TInt aError)
       
   253 {
       
   254     ELOG1( EJavaMMAPI, "CMMAVideoPlayer::CompletePrefetch + error = %d",aError);
       
   255     // Post KNotCompleteVideoError as KErrNone to the Java side, because
       
   256     // video can be played.
       
   257     if (aError == KNotCompleteVideoError)
       
   258     {
       
   259         LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::CompletePrefetch  KNotCompleteVideoError ");
       
   260         // release java
       
   261         PostActionCompleted(KErrNone);
       
   262     }
       
   263     else
       
   264     {
       
   265         LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::CompletePrefetch  CompleteVideoError ");
       
   266         // release java
       
   267         PostActionCompleted(aError);
       
   268     }
       
   269 
       
   270     if (aError == KErrNone || aError == KNotCompleteVideoError)
       
   271     {
       
   272         ChangeState(EPrefetched);
       
   273     }
       
   274     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::CompletePrefetch - ");
       
   275 }
       
   276 
       
   277 void CMMAVideoPlayer::PrepareDisplay()
       
   278 {
       
   279     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::PrepareDisplay +");
       
   280     // construction should have leaved if iDSAWindow does not exist
       
   281     __ASSERT_DEBUG(iDSAWindow,
       
   282                    User::Panic(_L("CMMVideoPlayer::iDSAWindow is null"),
       
   283                                KErrArgument));
       
   284 
       
   285     // Video must be initially not visible
       
   286     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::PrepareDisplay: Initially aborting DSA");
       
   287     iVideoPlayControllerCustomCommands.DirectScreenAccessEvent(EAbortDSA);
       
   288 
       
   289     //First place where we are certain that source size can be fetched
       
   290     TSize sourceSize;
       
   291 
       
   292     TInt err = iVideoControllerCustomCommands.GetVideoFrameSize(sourceSize);
       
   293 
       
   294     ELOG1( EJavaMMAPI, "MID::CMMAVideoPlayer::PrepareDisplay: GetVideoFrameSize err = %d", err);
       
   295 
       
   296     // Still we did not get the size of video
       
   297     if ((err != KErrNone) ||
       
   298             (sourceSize.iWidth <= 0) ||
       
   299             (sourceSize.iHeight <= 0))
       
   300     {
       
   301         LOG( EJavaMMAPI, EInfo, "MID::CMMAVideoPlayer::PrepareDisplay: No sourcesize found, using DSAWindow size");
       
   302         // setting size to window size (client rect)
       
   303         sourceSize = iDSAWindow->WindowSize();
       
   304     }
       
   305 
       
   306     // If 1x1 was got (the default size of form), it must be replaced
       
   307     // with a valid size as controller will not accept 1x1.
       
   308     if ((sourceSize.iWidth < KMMAVideoMinDimension) ||
       
   309             (sourceSize.iHeight < KMMAVideoMinDimension))
       
   310     {
       
   311         LOG( EJavaMMAPI, EInfo, "MID::CMMAVideoPlayer::PrepareDisplay: Unacceptable source size, using failsafe");
       
   312         // This is a special case and ought to be used only in
       
   313         // the rare case that real size is not got from stream.
       
   314         sourceSize = TSize(KMMAVideoMinDimension, KMMAVideoMinDimension);
       
   315     }
       
   316 
       
   317     iSourceSize = sourceSize;
       
   318 
       
   319     // If init has been already done
       
   320     if (iDisplay)
       
   321     {
       
   322         LOG( EJavaMMAPI, EInfo, "MID::CMMAVideoPlayer::PrepareDisplay: display exists, changing source size");
       
   323         SourceSizeChanged();
       
   324     }
       
   325 
       
   326     // Setting (in)visible if something has changed the DSA state
       
   327     // (e.g. prepare). If initDisplayMode is not called, this will always
       
   328     // set visibility to false.
       
   329     iDSAWindow->SetVisible(iDSAWindow->IsVisible(), EFalse);
       
   330     LOG( EJavaMMAPI, EInfo, "CMMAVideoPlayer::PrepareDisplay -");
       
   331 }
       
   332 
       
   333 EXPORT_C const TDesC& CMMAVideoPlayer::Type()
       
   334 {
       
   335     return KMMAVideoPlayer;
       
   336 }
       
   337 
       
   338 EXPORT_C TSize CMMAVideoPlayer::SourceSize()
       
   339 {
       
   340     return iSourceSize;
       
   341 }
       
   342 
       
   343 EXPORT_C MMMASnapshot::TEncoding CMMAVideoPlayer::TakeSnapshotL(TRequestStatus* aStatus,
       
   344         const TSize& /*aSize*/,
       
   345         const CMMAImageSettings& /*aSettings*/)
       
   346 {
       
   347     if (iEmptySnapshotImage)
       
   348     {
       
   349         // Ealier snapshot was not got with SnapshotBitmap method.
       
   350         User::Leave(KErrInUse);
       
   351     }
       
   352     // frame can't be got from video player, but TCK requires that it should
       
   353     // be available. So returning empty image
       
   354     iEmptySnapshotImage = new(ELeave) CFbsBitmap();
       
   355     User::LeaveIfError(iEmptySnapshotImage->Create(TSize(1, 1),
       
   356                        EColor4K));
       
   357 
       
   358 
       
   359     User::RequestComplete(aStatus, KErrNone);
       
   360 
       
   361     // Return raw bitmap encoding and thus SnapshotEncoded() should not
       
   362     // get called later on.
       
   363     return EBitmap;
       
   364 }
       
   365 
       
   366 EXPORT_C CFbsBitmap* CMMAVideoPlayer::SnapshotBitmap()
       
   367 {
       
   368     // snapshot is not supported, returning empty image
       
   369     CFbsBitmap* image = iEmptySnapshotImage;
       
   370 
       
   371     // ownership is transferred to caller
       
   372     iEmptySnapshotImage = NULL;
       
   373     return image;
       
   374 }
       
   375 
       
   376 EXPORT_C HBufC8* CMMAVideoPlayer::SnapshotEncoded()
       
   377 {
       
   378     // This method should never be called.
       
   379     // Asserted in debug build to be sure.
       
   380     __ASSERT_DEBUG(EFalse, User::Invariant());
       
   381 
       
   382     return NULL;
       
   383 }
       
   384 
       
   385 EXPORT_C void CMMAVideoPlayer::NotifyWithStringEvent(
       
   386     CMMAPlayerEvent::TEventType aEventType,
       
   387     const TDesC& aStringEventData)
       
   388 {
       
   389     PostStringEvent(aEventType, aStringEventData);
       
   390 }
       
   391 
       
   392 EXPORT_C MMMASnapshot* CMMAVideoPlayer::SnapshoterL()
       
   393 {
       
   394     return this;
       
   395 }
       
   396 
       
   397 void CMMAVideoPlayer::SourceSizeChanged()
       
   398 {
       
   399     iDisplay->SourceSizeChanged(iSourceSize);
       
   400     NotifyWithStringEvent(CMMAPlayerEvent::ESizeChanged, KVideoControlName);
       
   401 }
       
   402 
       
   403 //  END OF FILE