javauis/mmapi_qt/baseline/src.nga/cmmavideoplayer.cpp
branchRCL_3
changeset 24 0fd27995241b
child 26 dc7c549001d5
equal deleted inserted replaced
20:f9bb0fca356a 24: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 //  INCLUDE FILES
       
    19 #include <mmf/server/mmffile.h>
       
    20 #include <logger.h>
       
    21 
       
    22 #include "cmmavideoplayer.h"
       
    23 #include "mmmadisplay.h"
       
    24 #include "mmafunctionserver.h"
       
    25 #include "cmmasurfacewindow.h"
       
    26 
       
    27 // CONSTANTS
       
    28 _LIT(KVideoControlName, "VideoControl");
       
    29 
       
    30 CMMAVideoPlayer* CMMAVideoPlayer::NewLC(
       
    31     CMMAMMFResolver* aResolver)
       
    32 {
       
    33     CMMAVideoPlayer* self =
       
    34         new(ELeave) CMMAVideoPlayer(aResolver);
       
    35     CleanupStack::PushL(self);
       
    36     self->ConstructL();
       
    37     return self;
       
    38 }
       
    39 
       
    40 CMMAVideoPlayer::~CMMAVideoPlayer()
       
    41     {
       
    42     LOG(EJavaMMAPI,EInfo, "MMA::CMMAVideoPlayer::~CMMAVideoPlayer" );
       
    43 
       
    44     // Window is not able to send any
       
    45     // callback requests to UI from now.
       
    46     if (iSurfaceWindow)
       
    47     {
       
    48         iSurfaceWindow->SetDisplay(NULL);
       
    49     }
       
    50 
       
    51     if ( iDisplay && iDisplay->HasContainer() )
       
    52        {
       
    53        // Window will delete itself
       
    54        // after all pending events are processed
       
    55        // (lazy delete)
       
    56 //       iDisplay->UIGetCallback(
       
    57   //             *iSurfaceWindow, CMMASurfaceWindow::EDestroyWindow );
       
    58        iDisplay->GetCallbackInUiThread((TInt)CMMASurfaceWindow::EDestroyWindow );        	
       
    59        }
       
    60     else
       
    61     {
       
    62         delete iSurfaceWindow;
       
    63     }
       
    64 
       
    65     if (iDisplay)
       
    66     {
       
    67         TRAPD(err, iDisplay->SetWindowL(NULL));
       
    68         if (err != KErrNone)
       
    69         {
       
    70             __ASSERT_DEBUG(EFalse, User::Invariant());
       
    71         }
       
    72     }
       
    73 
       
    74     delete iEmptySnapshotImage;
       
    75     delete iActiveSchedulerWait;
       
    76 }
       
    77 
       
    78 CMMAVideoPlayer::CMMAVideoPlayer(
       
    79     CMMAMMFResolver* aResolver):
       
    80         CMMAAudioPlayer(aResolver),
       
    81         iVideoControllerCustomCommands(iController),
       
    82         iVideoPlayControllerCustomCommands(iController),
       
    83         iVideoPlaySurfaceSupportCustomCommands(iController)
       
    84 {
       
    85     iMMASurface.iPrevSurfaceAvailable = EFalse;
       
    86 }
       
    87 
       
    88 void CMMAVideoPlayer::ConstructL()
       
    89 {
       
    90     CMMAAudioPlayer::ConstructL();
       
    91     iActiveSchedulerWait = new(ELeave)CActiveSchedulerWait;
       
    92 }
       
    93 
       
    94 EXPORT_C void CMMAVideoPlayer::SetPlayerListenerObjectL(jobject aListenerObject,
       
    95         JNIEnv* aJni,
       
    96         MMMAEventPoster* aEventPoster)
       
    97 {
       
    98     CMMAPlayer::SetPlayerListenerObjectL(aListenerObject,
       
    99                                          aJni,
       
   100                                          aEventPoster);
       
   101 
       
   102     // this method must be called only ones
       
   103     __ASSERT_DEBUG(!iSurfaceWindow, User::Invariant());
       
   104 
       
   105     // create window for videoplayer
       
   106     // event poster is always MMAFunctionServer type.
       
   107 
       
   108     iSurfaceWindow = CMMASurfaceWindow::NewL(
       
   109                          static_cast< MMAFunctionServer* >(iEventPoster),
       
   110                          this);
       
   111 }
       
   112 
       
   113 EXPORT_C void CMMAVideoPlayer::SetDisplayL(MMMADisplay* aDisplay)
       
   114 {
       
   115     // now it is ready to draw
       
   116     iDisplay = aDisplay;
       
   117 		iDisplay->SetWindowL( iSurfaceWindow );
       
   118     iSurfaceWindow->SetDisplay( aDisplay );
       
   119     iDisplay->SetUIPlayer(this);
       
   120 
       
   121     
       
   122 /*
       
   123     // if state < prefeteched then we dont know actual source size yet
       
   124     // and it will be set after prefetch
       
   125     if ( iState >= EPrefetched )
       
   126         {
       
   127         SourceSizeChanged();
       
   128         }
       
   129      */ 
       
   130     }
       
   131 void CMMAVideoPlayer::RealizeL()
       
   132 {
       
   133     LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::RealizeL" );
       
   134     // DataSource must have at least 1 stream or
       
   135     // we must have file to play
       
   136     if ((iSourceStreams.Count() == 0) && !iFileName)
       
   137     {
       
   138         User::Leave(KErrNotEnoughStreams);
       
   139     }
       
   140 
       
   141     // If file locator is used, then file is prefetched
       
   142     // in realized state so that FramePositioningControl
       
   143     // can acquire frame count in REALIZED state
       
   144     if (iFileName)
       
   145     {
       
   146         PrefetchFileL();
       
   147         if (!iActiveSchedulerWait->IsStarted())
       
   148         {
       
   149             iActiveSchedulerWait->Start();
       
   150         }
       
   151         // If the player has not changed state during wait,
       
   152         // Then there is an error condition.
       
   153         if (iState != ERealized)
       
   154         {
       
   155             User::Leave(KErrNotSupported);
       
   156         }
       
   157     }
       
   158     else
       
   159     {
       
   160         CMMAPlayer::RealizeL();
       
   161     }
       
   162 }
       
   163 
       
   164 void CMMAVideoPlayer::PrefetchL()
       
   165 {
       
   166     LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::PrefetchL" );
       
   167     if (iFileName)
       
   168     {
       
   169         // File has already been prefetched when realizing
       
   170 
       
   171         // If initDisplayMode was called before prefetch,
       
   172         // then the display must notified about source size.
       
   173         if (iDisplay)
       
   174         {
       
   175             SourceSizeChanged();
       
   176         }
       
   177 
       
   178         PostActionCompletedFile();
       
   179         ChangeState( EPrefetched );
       
   180     }
       
   181     else
       
   182     {
       
   183         // Using TDes -- load the whole video
       
   184         iSourceStreams[ 0 ]->ReadAllL();
       
   185     }
       
   186     // CMMASourceStream will notify with ReadCompleted
       
   187 }
       
   188 
       
   189 EXPORT_C void CMMAVideoPlayer::ReadCompletedL(TInt aStatus, const TDesC8& aData)
       
   190 {
       
   191     LOG1( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::ReadCompletedL: status = %d", aStatus );
       
   192     if (aStatus < KErrNone)
       
   193     {
       
   194         PostActionCompleted(aStatus);
       
   195     }
       
   196     else
       
   197     {
       
   198         TRAPD(err, PrefetchDataL(aData));
       
   199         if (err != KErrNone)
       
   200         {
       
   201             PostActionCompleted(err);
       
   202         }
       
   203         // action completed event will be delivered from handleEvent
       
   204     }
       
   205 }
       
   206 
       
   207 void CMMAVideoPlayer::HandleEvent(const TMMFEvent& aEvent)
       
   208 {
       
   209     LOG1( EJavaMMAPI, EInfo,  "MMA:CMMAVideoPlayer::HandleEvent %d", aEvent.iEventType.iUid );
       
   210     
       
   211     // event KMMFEventCategoryPlaybackComplete is handled by both Video
       
   212     // and Audio players. first it should be handled by Video player
       
   213     if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete)
       
   214     {
       
   215         iSurfaceWindow->RemoveSurface();
       
   216     }
       
   217 
       
   218     // KNotCompleteVideoError can be notified when video is not complete
       
   219     // ( missing sound ) but still can be played. Because
       
   220     // CMMAAudioPlayer::HandleEvent fails with all negative error codes,
       
   221     // do not call it with KNotCompleteVideoError error when preparing.
       
   222     if ((aEvent.iErrorCode != KNotCompleteVideoError) ||
       
   223             (aEvent.iEventType != KMMFEventCategoryVideoPrepareComplete))
       
   224     {
       
   225         CMMAAudioPlayer::HandleEvent(aEvent);
       
   226     }
       
   227 
       
   228     if (aEvent.iEventType == KMMFEventCategoryVideoSurfaceCreated)
       
   229     {
       
   230         if (aEvent.iErrorCode == KErrNone)
       
   231         {
       
   232             TSurfaceId surfaceId;
       
   233             TRect cropRect;
       
   234             TVideoAspectRatio pixelAspectRatio;
       
   235 
       
   236             iVideoPlaySurfaceSupportCustomCommands.GetSurfaceParameters(surfaceId,
       
   237                     cropRect,
       
   238                     pixelAspectRatio);
       
   239 
       
   240             if (iMMASurface.iPrevSurfaceAvailable)
       
   241             {
       
   242                 // free Surface
       
   243                 TInt error = iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(iMMASurface.iPrevSurfaceId);
       
   244                 if (KErrNone != error)
       
   245                 {
       
   246                  	ELOG1( EJavaMMAPI, "CMMAVideoPlayer::HandleEvent:SurfaceRemoved error, %d", aEvent.iErrorCode);
       
   247                 }
       
   248             }
       
   249             iMMASurface.iPrevSurfaceId = surfaceId;
       
   250             iMMASurface.iPrevSurfaceAvailable = ETrue;
       
   251 
       
   252             iSurfaceWindow->SetSurfaceParameters(surfaceId,
       
   253                                                  cropRect,
       
   254                                                  pixelAspectRatio);
       
   255 
       
   256 						LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::HandleEvent: KMMFEventCategoryVideoSurfaceCreated, surface parameters set" );
       
   257         }
       
   258         else
       
   259         {
       
   260         		ELOG1( EJavaMMAPI,  "CMMAVideoPlayer::HandleEvent: error getting surface parameters, %d", aEvent.iErrorCode );
       
   261         }
       
   262     }
       
   263     else if (aEvent.iEventType == KMMFEventCategoryVideoSurfaceParametersChanged)
       
   264     {
       
   265         if (aEvent.iErrorCode == KErrNone)
       
   266         {
       
   267             TSurfaceId surfaceId;
       
   268             TRect cropRect;
       
   269             TVideoAspectRatio pixelAspectRatio;
       
   270 
       
   271             iVideoPlaySurfaceSupportCustomCommands.GetSurfaceParameters(surfaceId,
       
   272                     cropRect,
       
   273                     pixelAspectRatio);
       
   274 
       
   275             if (iMMASurface.iPrevSurfaceAvailable)
       
   276             {
       
   277                 // free Surface
       
   278                 TInt error = iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(iMMASurface.iPrevSurfaceId);
       
   279                 if (KErrNone != error)
       
   280                 {
       
   281                    	LOG1( EJavaMMAPI, EInfo, "CMMAVideoPlayer::HandleEvent:SurfaceRemoved error, %d", aEvent.iErrorCode);
       
   282                 }
       
   283             }
       
   284             iMMASurface.iPrevSurfaceAvailable = ETrue;
       
   285             iMMASurface.iPrevSurfaceId = surfaceId;
       
   286 
       
   287             iSurfaceWindow->SetChangedSurfaceParameters(surfaceId,
       
   288                     cropRect,
       
   289                     pixelAspectRatio);
       
   290 
       
   291 						LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::HandleEvent: KMMFEventCategoryVideoSurfaceParametersChanged" );
       
   292         }
       
   293         else
       
   294         {
       
   295           	ELOG1( EJavaMMAPI,  "CMMAVideoPlayer::HandleEvent: surface parameters changed error, %d", aEvent.iErrorCode );
       
   296         }
       
   297     }
       
   298     else if (aEvent.iEventType == KMMFEventCategoryVideoRemoveSurface)
       
   299     {
       
   300     	  if (aEvent.iErrorCode == KErrNone)
       
   301         {
       
   302            if (iMMASurface.iPrevSurfaceAvailable)
       
   303            {
       
   304                 // free Surface
       
   305                 TInt error = iVideoPlaySurfaceSupportCustomCommands.SurfaceRemoved(iMMASurface.iPrevSurfaceId);
       
   306                 if (KErrNone != error)
       
   307                 {
       
   308 				  ELOG1( EJavaMMAPI,  "CMMAVideoPlayer::HandleEvent:SurfaceRemoved error, %d", aEvent.iErrorCode);
       
   309                 }
       
   310                 iMMASurface.iPrevSurfaceAvailable = EFalse;
       
   311            }
       
   312         }
       
   313         else
       
   314         {
       
   315            ELOG1( EJavaMMAPI, "CMMAVideoPlayer::HandleEvent:KMMFEventCategoryVideoRemoveSurface error, %d", aEvent.iErrorCode);
       
   316         }
       
   317     }
       
   318     // video opened, preparing
       
   319     else if (aEvent.iEventType == KMMFEventCategoryVideoOpenComplete)
       
   320     {
       
   321         if (aEvent.iErrorCode == KErrNone)
       
   322         {
       
   323             TInt error = iVideoPlaySurfaceSupportCustomCommands.UseSurfaces();
       
   324     				ELOG1( EJavaMMAPI,  "MMA::CMMAVideoPlayer::HandleEvent::After UseSurfaces(), error = %d", error );
       
   325             TInt prepareError(iVideoPlayControllerCustomCommands.Prepare());
       
   326             if (prepareError != KErrNone)
       
   327             {
       
   328                 // opening failed, notifying java
       
   329                 PostActionCompleted(prepareError);
       
   330             }
       
   331         }
       
   332         else
       
   333         {
       
   334             // opening failed, notifying java
       
   335             PostActionCompleted(aEvent.iErrorCode);
       
   336         }
       
   337     }
       
   338     // final state of prefetch ( prepare completed )
       
   339     else if (aEvent.iEventType == KMMFEventCategoryVideoPrepareComplete)
       
   340     {
       
   341         // This callback must be handled differently depending on whether
       
   342         // player is created for a file locator or for a stream. When file
       
   343         // locator is used, this callback is made in realized state. For
       
   344         // stream it is made in prefetched state.
       
   345         PrepareDisplay();
       
   346         if (iFileName)
       
   347         {
       
   348             LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::HandleEvent: Using filename, change state to REALIZED" );
       
   349 
       
   350             // If there is an error condition, then the player state is not
       
   351             // changed, which indicates the error condition to StartL when
       
   352             // the ActiveSchedulerWait returns. KNotCompleteVideoError is not
       
   353             // considered as an error condition, instead it indicates that some
       
   354             // elements of the media cannot be played (e.g. video OR audio)
       
   355             if (aEvent.iErrorCode == KErrNone ||
       
   356                     aEvent.iErrorCode == KNotCompleteVideoError)
       
   357             {
       
   358                 ChangeState(ERealized);
       
   359             }
       
   360             __ASSERT_DEBUG(iActiveSchedulerWait->IsStarted(), User::Invariant());
       
   361             iActiveSchedulerWait->AsyncStop();
       
   362         }
       
   363         else
       
   364         {
       
   365             LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::HandleEvent: Not using filename, change state to PREFETCHED" );
       
   366             CompletePrefetch(aEvent.iErrorCode);
       
   367         }
       
   368     }
       
   369     else            // in case of any other event
       
   370     {
       
   371         if (aEvent.iErrorCode != KErrNone)
       
   372         {
       
   373             PostActionCompleted(aEvent.iErrorCode);   //some other error
       
   374         }
       
   375     }
       
   376 }
       
   377 
       
   378 void CMMAVideoPlayer::CompletePrefetch(TInt aError)
       
   379 {
       
   380     ELOG1( EJavaMMAPI,  "CMMAVideoPlayer::CompletePrefetch + error = %d",aError);
       
   381     // Post KNotCompleteVideoError as KErrNone to the Java side, because
       
   382     // video can be played.
       
   383     if (aError == KNotCompleteVideoError)
       
   384     {
       
   385         LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::CompletePrefetch  KNotCompleteVideoError ");
       
   386         // release java
       
   387         PostActionCompleted(KErrNone);
       
   388     }
       
   389     else
       
   390     {
       
   391         LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::CompletePrefetch  CompleteVideoError ");
       
   392         // release java
       
   393         PostActionCompleted(aError);
       
   394     }
       
   395 
       
   396     if (aError == KErrNone || aError == KNotCompleteVideoError)
       
   397     {
       
   398         ChangeState(EPrefetched);
       
   399     }
       
   400     LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::CompletePrefetch - ");
       
   401 }
       
   402 
       
   403 void CMMAVideoPlayer::PrepareDisplay()
       
   404 {
       
   405     LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::PrepareDisplay +" );
       
   406     // construction should have leaved if iSurfaceWindow does not exist
       
   407     __ASSERT_DEBUG(iSurfaceWindow,
       
   408                    User::Panic(_L("CMMVideoPlayer::iSurfaceWindow is null"),
       
   409                                KErrArgument));
       
   410 
       
   411     //First place where we are certain that source size can be fetched
       
   412     TSize sourceSize;
       
   413 
       
   414     TInt err = iVideoControllerCustomCommands.GetVideoFrameSize(sourceSize);
       
   415 
       
   416     ELOG1( EJavaMMAPI,  "MID::CMMAVideoPlayer::PrepareDisplay: GetVideoFrameSize err = %d", err );
       
   417 
       
   418     // Still we did not get the size of video
       
   419     if ((err != KErrNone) ||
       
   420             (sourceSize.iWidth <= 0) ||
       
   421             (sourceSize.iHeight <= 0))
       
   422     {
       
   423         LOG( EJavaMMAPI, EInfo,  "MID::CMMAVideoPlayer::PrepareDisplay: No sourcesize found, using SurfaceWindow size" );
       
   424         // setting size to window size (client rect)
       
   425         sourceSize = iSurfaceWindow->WindowSize();
       
   426     }
       
   427 
       
   428     // If 1x1 was got (the default size of form), it must be replaced
       
   429     // with a valid size as controller will not accept 1x1.
       
   430     if ((sourceSize.iWidth < KMMAVideoMinDimension) ||
       
   431             (sourceSize.iHeight < KMMAVideoMinDimension))
       
   432     {
       
   433         LOG( EJavaMMAPI, EInfo,  "MID::CMMAVideoPlayer::PrepareDisplay: Unacceptable source size, using failsafe" );
       
   434         // This is a special case and ought to be used only in
       
   435         // the rare case that real size is not got from stream.
       
   436         sourceSize = TSize(KMMAVideoMinDimension, KMMAVideoMinDimension);
       
   437     }
       
   438 
       
   439     iSourceSize = sourceSize;
       
   440 
       
   441     // If init has been already done
       
   442     if (iDisplay)
       
   443     {
       
   444         LOG( EJavaMMAPI, EInfo,  "MID::CMMAVideoPlayer::PrepareDisplay: display exists, changing source size" );
       
   445         SourceSizeChanged();
       
   446     }
       
   447 
       
   448     // Setting (in)visible if something has changed the DSA state
       
   449     // (e.g. prepare). If initDisplayMode is not called, this will always
       
   450     // set visibility to false.
       
   451     iSurfaceWindow->SetVisible(iSurfaceWindow->IsVisible(), EFalse);
       
   452     LOG( EJavaMMAPI, EInfo,  "CMMAVideoPlayer::PrepareDisplay -" );
       
   453 }
       
   454 
       
   455 EXPORT_C const TDesC& CMMAVideoPlayer::Type()
       
   456 {
       
   457     return KMMAVideoPlayer;
       
   458 }
       
   459 
       
   460 EXPORT_C TSize CMMAVideoPlayer::SourceSize()
       
   461 {
       
   462     return iSourceSize;
       
   463 }
       
   464 
       
   465 EXPORT_C MMMASnapshot::TEncoding CMMAVideoPlayer::TakeSnapshotL(TRequestStatus* aStatus,
       
   466         const TSize& /*aSize*/,
       
   467         const CMMAImageSettings& /*aSettings*/)
       
   468 {
       
   469     if (iEmptySnapshotImage)
       
   470     {
       
   471         // Ealier snapshot was not got with SnapshotBitmap method.
       
   472         User::Leave(KErrInUse);
       
   473     }
       
   474     // frame can't be got from video player, but TCK requires that it should
       
   475     // be available. So returning empty image
       
   476     iEmptySnapshotImage = new(ELeave) CFbsBitmap();
       
   477     User::LeaveIfError(iEmptySnapshotImage->Create(TSize(1, 1),
       
   478                        EColor4K));
       
   479 
       
   480 
       
   481     User::RequestComplete(aStatus, KErrNone);
       
   482 
       
   483     // Return raw bitmap encoding and thus SnapshotEncoded() should not
       
   484     // get called later on.
       
   485     return EBitmap;
       
   486 }
       
   487 
       
   488 EXPORT_C CFbsBitmap* CMMAVideoPlayer::SnapshotBitmap()
       
   489 {
       
   490     // snapshot is not supported, returning empty image
       
   491     CFbsBitmap* image = iEmptySnapshotImage;
       
   492 
       
   493     // ownership is transferred to caller
       
   494     iEmptySnapshotImage = NULL;
       
   495     return image;
       
   496 }
       
   497 
       
   498 EXPORT_C HBufC8* CMMAVideoPlayer::SnapshotEncoded()
       
   499 {
       
   500     // This method should never be called.
       
   501     // Asserted in debug build to be sure.
       
   502     __ASSERT_DEBUG(EFalse, User::Invariant());
       
   503 
       
   504     return NULL;
       
   505 }
       
   506 
       
   507 EXPORT_C void CMMAVideoPlayer::NotifyWithStringEvent(
       
   508     CMMAPlayerEvent::TEventType aEventType,
       
   509     const TDesC& aStringEventData)
       
   510 {
       
   511     PostStringEvent(aEventType, aStringEventData);
       
   512 }
       
   513 
       
   514 EXPORT_C MMMASnapshot* CMMAVideoPlayer::SnapshoterL()
       
   515 {
       
   516     return this;
       
   517 }
       
   518 
       
   519 void CMMAVideoPlayer::SourceSizeChanged()
       
   520 {
       
   521     iDisplay->SourceSizeChanged(iSourceSize);
       
   522     NotifyWithStringEvent(CMMAPlayerEvent::ESizeChanged, KVideoControlName);
       
   523 }
       
   524 
       
   525 //  END OF FILE