mmsharing/mmshengine/src/musengclipsession.cpp
changeset 15 ccd8e69b5392
parent 2 b31261fd4e04
child 20 e8be2c2e049d
child 22 496ad160a278
equal deleted inserted replaced
2:b31261fd4e04 15:ccd8e69b5392
     1 /*
       
     2 * Copyright (c) 2005 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: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // USER
       
    20 #include "musengclipsession.h"
       
    21 #include "musengclipsessionobserver.h"
       
    22 #include "musengsessionobserver.h"
       
    23 #include "musengmceoutsession.h"
       
    24 #include "musenglivesession.h"
       
    25 #include "musengmceutils.h"
       
    26 #include "musenglogger.h"
       
    27 
       
    28 // SYSTEM
       
    29 #include <mcemanager.h>
       
    30 #include <mcesession.h>
       
    31 #include <mcestreambundle.h>
       
    32 #include <mcefilesource.h>
       
    33 #include <mcemediastream.h>
       
    34 #include <mcevideostream.h>
       
    35 #include <mceaudiostream.h>
       
    36 #include <mcertpsink.h>
       
    37 #include <mcedisplaysink.h>
       
    38 #include <mcespeakersink.h>
       
    39 #include <mceamrcodec.h>
       
    40 #include <mcevideocodec.h>
       
    41 #include <DRMCommon.h>
       
    42 #include <f32file.h>
       
    43 
       
    44 
       
    45 // CONSTANTS
       
    46 
       
    47 const TInt64 KMicroSecondsInOneSecond = 1000000;
       
    48 const TInt KMusEngAmrBitRate = KMceAmrNbBitrate475;
       
    49 const TUint KMusEngAllowedAmrBitrates = KMceAllowedAmrNbBitrate475;
       
    50 
       
    51 const TInt KFastWindingFactor = 4;
       
    52 
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 // -----------------------------------------------------------------------------
       
    56 //
       
    57 EXPORT_C CMusEngClipSession* CMusEngClipSession::NewL(
       
    58                         const TRect& aRect,
       
    59                         MMusEngSessionObserver& aSessionObserver,
       
    60                         MMusEngOutSessionObserver& aOutSessionObserver,
       
    61                         MMusEngClipSessionObserver& aClipSessionObserver,
       
    62                         TUint aSipProfileId )
       
    63     {
       
    64     CMusEngClipSession* self = new( ELeave ) CMusEngClipSession(
       
    65                                                     aSessionObserver,
       
    66                                                     aOutSessionObserver,
       
    67                                                     aClipSessionObserver,
       
    68                                                     aRect );
       
    69     CleanupStack::PushL( self );
       
    70     self->ConstructL( aSipProfileId );
       
    71     CleanupStack::Pop( self );
       
    72     return self;
       
    73     }
       
    74 
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 CMusEngClipSession::~CMusEngClipSession()
       
    81     {
       
    82     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::~CMusEngClipSession()" )
       
    83     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::~CMusEngClipSession()" )
       
    84     }
       
    85 
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 EXPORT_C void CMusEngClipSession::SetClipL( const TDesC& aFileName )
       
    92     {
       
    93     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::SetClipL(...)" )
       
    94 
       
    95     __ASSERT_ALWAYS( !IsProtectedFileL( aFileName ),
       
    96                      User::Leave( KErrPermissionDenied ) );
       
    97     
       
    98     if ( iSession )
       
    99         {
       
   100         CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   101         file->UpdateL( aFileName );
       
   102         }
       
   103 
       
   104     iFileName = aFileName;
       
   105 
       
   106     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::SetClipL(...)" )
       
   107 
       
   108     }
       
   109 
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // Since MCE does not at the moment support SetFastForwardL function, this
       
   113 // functionality is implemented by taking a timestamp when forwarding is
       
   114 // started and calculating a new position when it is ended.
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 EXPORT_C void CMusEngClipSession::FastForwardL( TBool aUseFFWD )
       
   118     {
       
   119     MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::FastForward(%d)", aUseFFWD )
       
   120 
       
   121     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   122 
       
   123     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   124 
       
   125     if ( aUseFFWD )
       
   126         {
       
   127         // Ignore if we are already fastforwarding
       
   128         if ( iFFWDStartTime.Int64() > 0 )
       
   129             {
       
   130             return;
       
   131             }
       
   132 
       
   133         // Stop rewinding if ongoing, else just pause file source
       
   134         if ( iFRWDStartTime.Int64() > 0 )
       
   135             {
       
   136             FastRewindL( EFalse );
       
   137             }
       
   138         else
       
   139             {
       
   140             file->DisableL();
       
   141             }
       
   142             
       
   143         // Get timestamp for starttime
       
   144         iFFWDStartTime.HomeTime();
       
   145         }
       
   146     else
       
   147         {
       
   148         // Leave if we are not fastforwarding
       
   149         if ( iFFWDStartTime.Int64() == 0 )
       
   150             {
       
   151             User::Leave( KErrAlreadyExists );
       
   152             }
       
   153 
       
   154         // Set new position
       
   155         file->SetPositionL( PositionMicroSecondsL( ETrue ) );
       
   156         MUS_LOG( "                 SetPositionL returned without error " )
       
   157         
       
   158         // Reset timer
       
   159         iFFWDStartTime = TTime( 0 );
       
   160         }
       
   161 
       
   162     MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::FastForward(%d)", aUseFFWD )
       
   163     }
       
   164 
       
   165 
       
   166 // -----------------------------------------------------------------------------
       
   167 // Since MCE does not at the moment support SetFastRewindL function, this
       
   168 // functionality is implemented by taking a timestamp when rewinding is
       
   169 // started and calculating a new position when it is ended.
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 EXPORT_C void CMusEngClipSession::FastRewindL( TBool aUseFRWD )
       
   173     {
       
   174     MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::FastRewind(%d)", aUseFRWD )
       
   175 
       
   176     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   177 
       
   178     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   179 
       
   180     if ( aUseFRWD )
       
   181         {
       
   182         // Ignore if we are already fastrewinding
       
   183         if ( iFRWDStartTime.Int64() > 0 )
       
   184             {
       
   185             return;
       
   186             }
       
   187 
       
   188         // Stop fastforwarding if ongoing, else just pause file source
       
   189         if ( iFFWDStartTime.Int64() > 0 )
       
   190             {
       
   191             FastForwardL( EFalse );
       
   192             }
       
   193         else
       
   194             {
       
   195             file->DisableL();
       
   196             }
       
   197             
       
   198         // Get timestamp for starttime
       
   199         iFRWDStartTime.HomeTime();
       
   200         }
       
   201     else
       
   202         {
       
   203         // Leave if we are not fastrewinding
       
   204         if ( iFRWDStartTime.Int64() == 0 )
       
   205             {
       
   206             User::Leave( KErrAlreadyExists );
       
   207             }
       
   208 
       
   209         // Set new position
       
   210         file->SetPositionL( PositionMicroSecondsL( ETrue ) );
       
   211         MUS_LOG( "                 SetPositionL returned without error " )
       
   212         
       
   213         // Reset timer
       
   214         iFRWDStartTime = TTime( 0 );
       
   215         }
       
   216 
       
   217     MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::FastRewind(%d)", aUseFRWD  )
       
   218     }
       
   219 
       
   220 
       
   221 // -----------------------------------------------------------------------------
       
   222 //
       
   223 // -----------------------------------------------------------------------------
       
   224 //
       
   225 EXPORT_C TTimeIntervalSeconds CMusEngClipSession::PositionL()
       
   226     {
       
   227     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PositionL()" )
       
   228     
       
   229     TTimeIntervalMicroSeconds currentPosition = PositionMicroSecondsL();
       
   230     
       
   231     MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::PositionL(), pos:%d", 
       
   232               currentPosition.Int64() )
       
   233     return TTimeIntervalSeconds( static_cast<TInt>( 
       
   234                     currentPosition.Int64() / KMicroSecondsInOneSecond ) );
       
   235     }
       
   236 
       
   237 
       
   238 // -----------------------------------------------------------------------------
       
   239 //
       
   240 // -----------------------------------------------------------------------------
       
   241 //
       
   242 EXPORT_C TTimeIntervalSeconds CMusEngClipSession::DurationL()
       
   243     {
       
   244     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::DurationL()" )
       
   245 
       
   246     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   247 
       
   248     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   249 
       
   250     TTimeIntervalMicroSeconds duration = file->DurationL();
       
   251 
       
   252     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DurationL()" )
       
   253     return TTimeIntervalSeconds(
       
   254             static_cast<TInt>( duration.Int64() / KMicroSecondsInOneSecond ) );
       
   255 
       
   256     }
       
   257 
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 //
       
   261 // -----------------------------------------------------------------------------
       
   262 //
       
   263 EXPORT_C void CMusEngClipSession::SetPositionL (
       
   264                         const TTimeIntervalSeconds& aPosition )
       
   265     {
       
   266     MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::SetPositionL (%d)",
       
   267               aPosition.Int() )
       
   268 
       
   269     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   270 
       
   271     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   272 
       
   273     TTimeIntervalMicroSeconds position( 
       
   274             KMicroSecondsInOneSecond * static_cast<TInt64>(aPosition.Int()) );
       
   275 
       
   276     if ( position == 0 )
       
   277         {
       
   278         iRewindedToBeginning = ETrue;
       
   279         }
       
   280         
       
   281     file->SetPositionL( position );
       
   282 
       
   283     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::SetPositionL ()" )
       
   284     }
       
   285 
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 // -----------------------------------------------------------------------------
       
   290 //
       
   291 EXPORT_C void CMusEngClipSession::TranscodeL( const TFileName& aFileName )
       
   292     {
       
   293     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::TranscodeL(...)" )
       
   294 
       
   295     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   296 
       
   297     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   298 
       
   299     const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
       
   300 
       
   301     for ( TInt i = 0; i < streams.Count(); ++i )
       
   302         {
       
   303         if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired )
       
   304             {
       
   305             if ( streams[i]->Type() == KMceAudio )
       
   306                 {
       
   307                 AddAmrCodecL( static_cast<CMceAudioStream&>( *streams[i] ) );
       
   308                 }
       
   309             else
       
   310                 {
       
   311                 AddVideoCodecL( static_cast<CMceVideoStream&>( *streams[i] ) );
       
   312                 }
       
   313             }
       
   314         }
       
   315 
       
   316     file->TranscodeL( aFileName );
       
   317 
       
   318     iTranscodingOngoing = ETrue;
       
   319     
       
   320     iTranscodingDestFileName = aFileName;
       
   321 
       
   322     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::TranscodeL(...)" )
       
   323     }
       
   324 
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 //
       
   328 // -----------------------------------------------------------------------------
       
   329 //
       
   330 EXPORT_C void CMusEngClipSession::CancelTranscodeL()
       
   331     {
       
   332     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CancelTranscodeL()" )
       
   333 
       
   334     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   335 
       
   336     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   337 
       
   338     TRAPD( err, file->CancelTranscodeL() );
       
   339     err = err; // Silence warning in UREL build
       
   340     MUS_LOG1( "mus: [ENGINE] - cancel result %d", err )
       
   341     // Even if cancel fails, try to delete the partial clip
       
   342 
       
   343     MUS_LOG( "mus: [ENGINE] - delete the partially converted clip" )
       
   344     RFs fs;
       
   345     User::LeaveIfError( fs.Connect() );
       
   346     CleanupClosePushL( fs );
       
   347 
       
   348     CFileMan* fileMan = CFileMan::NewL( fs );    
       
   349     CleanupStack::PushL( fileMan );
       
   350 
       
   351     MUS_LOG_TDESC8( "mus: [ENGINE] - trascoding destination filename",
       
   352                     iTranscodingDestFileName )
       
   353     err = fileMan->Delete( iTranscodingDestFileName );
       
   354     MUS_LOG1( "mus: [ENGINE] - file delete result %d", err )
       
   355 
       
   356     CleanupStack::PopAndDestroy( fileMan );
       
   357     CleanupStack::PopAndDestroy(); // fs
       
   358 
       
   359     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CancelTranscodeL()" )
       
   360     }
       
   361 
       
   362 
       
   363 // -----------------------------------------------------------------------------
       
   364 //
       
   365 // -----------------------------------------------------------------------------
       
   366 //
       
   367 EXPORT_C void CMusEngClipSession::PlayL()
       
   368     {
       
   369     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PlayL()" )
       
   370 
       
   371     __ASSERT_ALWAYS( iSession &&
       
   372                      iFFWDStartTime.Int64() == 0 &&
       
   373                      iFRWDStartTime.Int64() == 0, 
       
   374                      User::Leave( KErrNotReady ) );                     
       
   375 
       
   376     
       
   377     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   378 
       
   379     if ( !file->IsEnabled() )
       
   380         {
       
   381         file->EnableL();
       
   382         
       
   383         iClipEnded = EFalse;
       
   384         // No need to enable audio separarely
       
   385         }
       
   386     else
       
   387         {
       
   388         MUS_LOG( "mus: [ENGINE]    File is already enabled, ignore request" )
       
   389         }
       
   390         
       
   391     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::PlayL()" )
       
   392     }
       
   393 
       
   394 
       
   395 // -----------------------------------------------------------------------------
       
   396 // 
       
   397 // -----------------------------------------------------------------------------
       
   398 //
       
   399 EXPORT_C void CMusEngClipSession::PauseL()
       
   400     {
       
   401     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PauseL()" )
       
   402 
       
   403     __ASSERT_ALWAYS( iSession &&
       
   404                      iFFWDStartTime.Int64() == 0 &&
       
   405                      iFRWDStartTime.Int64() == 0, 
       
   406                      User::Leave( KErrNotReady ) );  
       
   407 
       
   408     
       
   409     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   410     
       
   411     if ( file->IsEnabled() )
       
   412         {
       
   413         file->DisableL();
       
   414 
       
   415         // No need to disable audio separarely
       
   416         }
       
   417     else
       
   418         {
       
   419         MUS_LOG( "mus: [ENGINE]    File is already disabled, ignore request" )
       
   420         }
       
   421         
       
   422     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::PauseL()" )
       
   423     }
       
   424 
       
   425 
       
   426 // -----------------------------------------------------------------------------
       
   427 //
       
   428 // -----------------------------------------------------------------------------
       
   429 //
       
   430 EXPORT_C TBool CMusEngClipSession::IsPlayingL()
       
   431     {
       
   432     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   433     
       
   434     return ( MusEngMceUtils::GetFileSourceL( *iSession )->IsEnabled() );
       
   435     }
       
   436 
       
   437 
       
   438 // -----------------------------------------------------------------------------
       
   439 //
       
   440 // -----------------------------------------------------------------------------
       
   441 //
       
   442 void CMusEngClipSession::CompleteSessionStructureL(
       
   443                                             CMceStreamBundle& aLocalBundle )
       
   444     {
       
   445     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CompleteSessionStructureL()" )
       
   446 
       
   447     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   448     __ASSERT_ALWAYS( iFileName != KNullDesC(), User::Leave( KErrNotReady ) );
       
   449 
       
   450     // Create outgoing video stream
       
   451     CMceVideoStream* videoStream = CMceVideoStream::NewLC();
       
   452     
       
   453     CMceRtpSink* rtpsink = CMceRtpSink::NewLC();
       
   454     videoStream->AddSinkL( rtpsink );
       
   455     CleanupStack::Pop( rtpsink );
       
   456 
       
   457     CMceFileSource* fileSource = CMceFileSource::NewLC( *iManager,
       
   458                                                         iFileName );
       
   459     fileSource->DisableL(); // Start session in pause mode.
       
   460     videoStream->SetSourceL( fileSource );
       
   461     CleanupStack::Pop( fileSource );
       
   462 
       
   463     iSession->AddStreamL( videoStream );
       
   464     CleanupStack::Pop( videoStream );
       
   465 
       
   466     ConstructAudioStructureL( aLocalBundle );
       
   467 
       
   468     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CompleteSessionStructureL()" )
       
   469     }
       
   470 
       
   471 
       
   472 // -----------------------------------------------------------------------------
       
   473 // Checks that that there is no need for transcoding before calling
       
   474 // overridden base class variant of this function.
       
   475 // -----------------------------------------------------------------------------
       
   476 //
       
   477 void CMusEngClipSession::EstablishSessionL()
       
   478     {
       
   479     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::EstablishSessionL()" )
       
   480 
       
   481     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   482 
       
   483     const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
       
   484 
       
   485     TBool transcodingRequired = EFalse;
       
   486     
       
   487     if ( iVideoCodecList )
       
   488         {
       
   489         MUS_LOG_TDESC8( "iVideoCodecList: ", iVideoCodecList->Des() )
       
   490         }
       
   491     
       
   492     CMceVideoStream* videoStream = NULL;
       
   493     for ( TInt i = 0; i < streams.Count(); ++i )
       
   494         {
       
   495         if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired )
       
   496             {
       
   497             transcodingRequired = ETrue;
       
   498             }
       
   499         else if ( streams[i]->Type() == KMceVideo &&
       
   500                   !IsH264Supported() )
       
   501             {
       
   502             MUS_LOG( "                -> video stream found!!!" )
       
   503             videoStream = static_cast<CMceVideoStream*>( streams[i] );
       
   504             
       
   505             //transcoding of H264 is not needed only if we know explicitly
       
   506             //that the peer supports it (from OPTIONS response)
       
   507                             
       
   508             const RPointerArray<CMceVideoCodec>& codecs = videoStream->Codecs();
       
   509             for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
       
   510                 {
       
   511                 if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() )                     
       
   512                     {
       
   513                     transcodingRequired = ETrue;
       
   514                     MUS_LOG( " -> Removing H264 codec from video stream" )
       
   515                     videoStream->RemoveCodecL( *codecs[codecIndex] );
       
   516                     codecIndex = 0;
       
   517                     }
       
   518                 }
       
   519             
       
   520             if ( codecs.Count() == 0)
       
   521                 {
       
   522                 // At least one codec should be in the stream list. 
       
   523                 MUS_LOG( " -> Adding codec, since codecs list is empty " )
       
   524                 AddVideoCodecL( *videoStream );  
       
   525                 }                
       
   526             } 
       
   527         }
       
   528 
       
   529     if ( transcodingRequired )
       
   530         {
       
   531         iClipSessionObserver.TranscodingNeeded();
       
   532         }
       
   533     else
       
   534         {                
       
   535         CMusEngMceOutSession::EstablishSessionL();
       
   536         // Now session state is right to adjust volume
       
   537         SetSpeakerVolumeL( VolumeL() );
       
   538         }
       
   539 
       
   540     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::EstablishSessionL()" )
       
   541     }
       
   542 
       
   543 // -----------------------------------------------------------------------------
       
   544 // Implemented for MMceStreamObserver
       
   545 // -----------------------------------------------------------------------------
       
   546 //
       
   547 void CMusEngClipSession::StreamStateChanged( CMceMediaStream& aStream )
       
   548     {
       
   549     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::StreamStateChanged()" )
       
   550     
       
   551     if ( !iSession )
       
   552         {
       
   553         return;
       
   554         }
       
   555         
       
   556     DetermineBufferingPeriod( aStream );
       
   557     
       
   558     CMusEngMceSession::StreamStateChanged( aStream );
       
   559     
       
   560     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::StreamStateChanged()" )
       
   561     }
       
   562 
       
   563 // -----------------------------------------------------------------------------
       
   564 // Implemented for MMceStreamObserver
       
   565 // -----------------------------------------------------------------------------
       
   566 //
       
   567 void CMusEngClipSession::StreamStateChanged( CMceMediaStream& aStream,
       
   568                                              CMceMediaSource& aSource )
       
   569     {
       
   570     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::StreamStateChanged( src )" )
       
   571     
       
   572     if ( !iSession )
       
   573         {
       
   574         return;
       
   575         }
       
   576 
       
   577     MUS_ENG_LOG_STREAM_STATE( aStream )
       
   578     
       
   579     DetermineBufferingPeriod( aStream );
       
   580 
       
   581     if ( aStream.State() == CMceMediaStream::ETranscoding )
       
   582         {
       
   583         CMceFileSource* file = static_cast<CMceFileSource*>(aStream.Source());
       
   584         TInt progressPercentage = 0;
       
   585         TRAP_IGNORE( progressPercentage = file->TranscodingProgressL() )
       
   586         iClipSessionObserver.TranscodingProgressed( progressPercentage );
       
   587         }
       
   588     else if ( aStream.State() == CMceMediaStream::EInitialized )
       
   589         {
       
   590         if ( iTranscodingOngoing )
       
   591             {
       
   592             MUS_LOG( "mus: [ENGINE]     Transcoding completed." )
       
   593             
       
   594             // Filename has been updated in MCE side but unfortunately
       
   595             // there's no getter for the filename in API.
       
   596             iFileName = iTranscodingDestFileName;
       
   597         
       
   598             iTranscodingOngoing = EFalse;
       
   599             
       
   600             iClipSessionObserver.TranscodingCompletedInit();  
       
   601                 
       
   602             TRAPD( error, EstablishSessionL() )
       
   603             if ( error != KErrNone )
       
   604                 {
       
   605                 iSessionObserver.SessionFailed();
       
   606                 }
       
   607                               
       
   608             // Next call does not return before session establishment
       
   609             iClipSessionObserver.TranscodingCompletedFinalize();                           
       
   610             }
       
   611         }
       
   612     else if ( aStream.State() == CMceMediaStream::ETranscodingRequired &&
       
   613               iTranscodingOngoing )
       
   614         {
       
   615         MUS_LOG( "mus: [ENGINE]     Transcoding failed." )
       
   616         
       
   617         iClipSessionObserver.TranscodingFailed();
       
   618         iTranscodingOngoing = EFalse;
       
   619         }
       
   620     else if ( HasClipEnded() )
       
   621         {
       
   622         MUS_LOG( "mus: [ENGINE]     Clip ended." )
       
   623         
       
   624         iDelayFileEndingPos = 0;
       
   625         iClipEnded = ETrue;
       
   626         
       
   627         iClipSessionObserver.EndOfClip();
       
   628         }
       
   629     else
       
   630         {
       
   631         // Cannot handle, forward to the ancestor class
       
   632         CMusEngMceSession::StreamStateChanged( aStream, aSource );
       
   633         }
       
   634 
       
   635     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::StreamStateChanged( src )" )
       
   636     }
       
   637 
       
   638 // -----------------------------------------------------------------------------
       
   639 //
       
   640 // -----------------------------------------------------------------------------
       
   641 //
       
   642 CMusEngClipSession::CMusEngClipSession(
       
   643                         MMusEngSessionObserver& aSessionObserver,
       
   644                         MMusEngOutSessionObserver& aOutSessionObserver,
       
   645                         MMusEngClipSessionObserver& aClipSessionObserver,
       
   646                         const TRect& aRect )
       
   647     : CMusEngMceOutSession( aRect,
       
   648                             aSessionObserver,
       
   649                             aOutSessionObserver ),
       
   650       iClipSessionObserver( aClipSessionObserver )
       
   651     {
       
   652     }
       
   653 
       
   654 
       
   655 // -----------------------------------------------------------------------------
       
   656 //
       
   657 // -----------------------------------------------------------------------------
       
   658 //
       
   659 void CMusEngClipSession::ConstructL( TUint aSipProfileId )
       
   660     {
       
   661     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructL(...)" )
       
   662 
       
   663     CMusEngMceOutSession::ConstructL( aSipProfileId );
       
   664 
       
   665     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructL(...)" )
       
   666     }
       
   667 
       
   668 
       
   669 // -----------------------------------------------------------------------------
       
   670 // Check is file DRM protected.
       
   671 //
       
   672 // -----------------------------------------------------------------------------
       
   673 //
       
   674 TBool CMusEngClipSession::IsProtectedFileL( const TDesC& aClipFile )
       
   675     {
       
   676     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::IsProtectedFileL(...)" )
       
   677 
       
   678     TBool isDRMProtected = EFalse;
       
   679     DRMCommon* drmapi = DRMCommon::NewL();
       
   680     CleanupStack::PushL( drmapi );
       
   681 
       
   682     User::LeaveIfError( drmapi->Connect() );
       
   683     //Check DRM file protection
       
   684     User::LeaveIfError( drmapi->IsProtectedFile( aClipFile, isDRMProtected ) );
       
   685     drmapi->Disconnect();
       
   686 
       
   687     CleanupStack::PopAndDestroy( drmapi );
       
   688 
       
   689     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::IsProtectedFileL(...)" )
       
   690     return isDRMProtected;
       
   691     }
       
   692 
       
   693 
       
   694 // -----------------------------------------------------------------------------
       
   695 //
       
   696 // -----------------------------------------------------------------------------
       
   697 //
       
   698 void CMusEngClipSession::AddAmrCodecL( CMceAudioStream& aAudioStream )
       
   699     {
       
   700     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddAmrCodecL" )
       
   701 
       
   702     // Remove old codecs
       
   703 
       
   704     while ( aAudioStream.Codecs().Count() > 0 )
       
   705         {
       
   706         aAudioStream.RemoveCodecL( *aAudioStream.Codecs()[0] );
       
   707         }
       
   708 
       
   709     // Create AMR codec instance
       
   710 
       
   711     const RPointerArray<const CMceAudioCodec>& supportedCodecs =
       
   712                                             iManager->SupportedAudioCodecs();
       
   713 
       
   714     CMceAudioCodec* amr = NULL;
       
   715 
       
   716     for ( TInt i = 0; i < supportedCodecs.Count(); ++i )
       
   717         {
       
   718         if ( supportedCodecs[i]->SdpName() == KMceSDPNameAMR() )
       
   719             {
       
   720             amr = supportedCodecs[i]->CloneL();
       
   721             CleanupStack::PushL( amr );
       
   722 
       
   723             User::LeaveIfError(
       
   724                     amr->SetAllowedBitrates( KMusEngAllowedAmrBitrates ) );
       
   725             User::LeaveIfError( amr->SetBitrate( KMusEngAmrBitRate ) );
       
   726             aAudioStream.AddCodecL( amr );
       
   727 
       
   728             CleanupStack::Pop( amr );
       
   729             break; // We must have only one codec
       
   730             }
       
   731         }
       
   732 
       
   733     __ASSERT_ALWAYS( amr, User::Leave( KErrNotFound ) );
       
   734 
       
   735     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddAmrCodecL" )
       
   736     }
       
   737 
       
   738 
       
   739 // -----------------------------------------------------------------------------
       
   740 // Create codec instance, H264 is used only if other end supports it for sure,
       
   741 // otherwise H263 is used.
       
   742 // -----------------------------------------------------------------------------
       
   743 //
       
   744 void CMusEngClipSession::AddVideoCodecL( CMceVideoStream& aVideoStream )
       
   745     {
       
   746     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddVideoCodecL" )
       
   747 
       
   748     // Remove old codecs
       
   749 
       
   750     while ( aVideoStream.Codecs().Count() > 0 )
       
   751         {
       
   752         aVideoStream.RemoveCodecL( *aVideoStream.Codecs()[0] );
       
   753         }
       
   754 
       
   755     const RPointerArray<const CMceVideoCodec>& supportedCodecs =
       
   756                                             iManager->SupportedVideoCodecs();
       
   757 
       
   758     CMceVideoCodec* addedCodec = NULL;
       
   759     
       
   760     TPtrC8 addedCodecName = 
       
   761             IsH264Supported() ? KMceSDPNameH264() : KMceSDPNameH2632000();
       
   762     
       
   763     MUS_LOG_TDESC8( "mus: [ENGINE] adding codec : ", addedCodecName ); 
       
   764             
       
   765     for ( TInt i = 0; i < supportedCodecs.Count(); ++i )
       
   766         {
       
   767         if ( supportedCodecs[i]->SdpName() == addedCodecName )
       
   768             {
       
   769             addedCodec = supportedCodecs[i]->CloneL();
       
   770             CleanupStack::PushL( addedCodec );
       
   771             aVideoStream.AddCodecL( addedCodec );
       
   772             CleanupStack::Pop( addedCodec );
       
   773             break; // We must have only one codec
       
   774             }
       
   775         }
       
   776 
       
   777     __ASSERT_ALWAYS( addedCodec, User::Leave( KErrNotFound ) );
       
   778 
       
   779     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddVideoCodecL" )
       
   780     }
       
   781 
       
   782 // -----------------------------------------------------------------------------
       
   783 //
       
   784 // -----------------------------------------------------------------------------
       
   785 //
       
   786 TBool CMusEngClipSession::HasClipEnded()
       
   787     {
       
   788     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::HasClipEnded()" )
       
   789 
       
   790     TBool hasClipEnded = EFalse;
       
   791 
       
   792     if ( iSession )
       
   793         {
       
   794         
       
   795         CMceVideoStream* videoOut = NULL;
       
   796         
       
   797         TRAPD( error, 
       
   798                videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession ) );
       
   799         if( error != KErrNone ) 
       
   800             {
       
   801             MUS_LOG1( "mus: [ENGINE]     Error in GetVideoOutStreamL #%d", error )
       
   802             return hasClipEnded;
       
   803             }
       
   804 
       
   805         CMceFileSource* filesource = NULL;
       
   806         TRAP( error, filesource = MusEngMceUtils::GetFileSourceL( *iSession ) )
       
   807 
       
   808         if ( error == KErrNone )
       
   809             {
       
   810             TTimeIntervalMicroSeconds position;
       
   811             TTimeIntervalMicroSeconds duration;
       
   812             TRAP( error, position = filesource->PositionL() );
       
   813             TRAPD( error1, duration = filesource->DurationL() );
       
   814             if ( error != KErrNone || error1 != KErrNone )
       
   815                 {
       
   816                 return hasClipEnded;
       
   817                 }
       
   818                 
       
   819             MUS_LOG2( "mus: [ENGINE]    position = %Ld, duration = %Ld", 
       
   820                         position.Int64(), 
       
   821                         duration.Int64() )
       
   822                         
       
   823             TRAP( error, hasClipEnded = 
       
   824                         ( position.Int64() == 0 && 
       
   825                           !filesource->IsEnabled() && 
       
   826                           videoOut->State() == CMceMediaStream::EDisabled ) )
       
   827             if(  hasClipEnded )
       
   828                 {
       
   829                 MUS_LOG( "mus: [ENGINE]     End of clip" )
       
   830                 }
       
   831             }
       
   832         }
       
   833 
       
   834     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::HasClipEnded()" )
       
   835     return hasClipEnded;
       
   836     }
       
   837 
       
   838 
       
   839 // -----------------------------------------------------------------------------
       
   840 //
       
   841 // -----------------------------------------------------------------------------
       
   842 //
       
   843 TTimeIntervalMicroSeconds CMusEngClipSession::PositionMicroSecondsL( 
       
   844     TBool aActualPosition )
       
   845     {
       
   846     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   847 
       
   848     CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession );
       
   849 
       
   850     TTimeIntervalMicroSeconds position = file->PositionL();
       
   851     TTimeIntervalMicroSeconds duration = file->DurationL();
       
   852        
       
   853     TTimeIntervalMicroSeconds calculatedPosition;
       
   854     
       
   855     // Adjust position if we are fastforwarding or -rewinding
       
   856     if ( iFFWDStartTime.Int64() != 0 )
       
   857         {
       
   858         TTime now;
       
   859         now.HomeTime();
       
   860         calculatedPosition = KFastWindingFactor *
       
   861                              now.MicroSecondsFrom( iFFWDStartTime ).Int64() +
       
   862                              position.Int64();
       
   863         if ( calculatedPosition > duration )
       
   864             {
       
   865             calculatedPosition = duration;
       
   866             }
       
   867         }
       
   868     else if ( iFRWDStartTime.Int64() != 0 )
       
   869         {
       
   870         TTime now;
       
   871         now.HomeTime();
       
   872         calculatedPosition = position.Int64() -
       
   873                              KFastWindingFactor *
       
   874                              now.MicroSecondsFrom( iFRWDStartTime ).Int64();
       
   875         if ( calculatedPosition < 0 )
       
   876             {
       
   877             calculatedPosition = 0;
       
   878             }
       
   879             
       
   880         if ( calculatedPosition == 0 )
       
   881             {
       
   882             iRewindedToBeginning = ETrue;
       
   883             }
       
   884         }
       
   885     else
       
   886         {
       
   887         calculatedPosition = position;
       
   888         }
       
   889     
       
   890     if ( !aActualPosition )
       
   891         {
       
   892         calculatedPosition = 
       
   893             GetVideoSinkRelativeFilePos( calculatedPosition, duration );
       
   894         }
       
   895         
       
   896     return calculatedPosition;
       
   897     }
       
   898     
       
   899 
       
   900 // -----------------------------------------------------------------------------
       
   901 // If member file contains audio, add appropriate amount of audio streams to
       
   902 // session structure
       
   903 // -----------------------------------------------------------------------------
       
   904 //
       
   905 void CMusEngClipSession::ConstructAudioStructureL(
       
   906                                             CMceStreamBundle& aLocalBundle )
       
   907     {
       
   908     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructAudioStructureL()" )
       
   909 
       
   910     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   911     
       
   912     // There is no clip audio present in operator variant
       
   913     if ( iOperatorVariant )
       
   914         {
       
   915         MUS_LOG( "                 Operator variant, no audio constructed" )
       
   916         MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructAudioStructureL()" )
       
   917         return;
       
   918         }
       
   919 
       
   920     CMceFileSource* fileSource = MusEngMceUtils::GetFileSourceL( *iSession );
       
   921 
       
   922     TInt audioElementCount = fileSource->MediaElementCountL( KMceAudio );
       
   923 
       
   924     MUS_LOG1( "mus: [ENGINE]    File contains %d audio elements",
       
   925               audioElementCount )
       
   926 
       
   927     for ( TInt i = 0; i < audioElementCount; ++i )
       
   928         {
       
   929         fileSource->SetCurrentMediaElementL( KMceAudio, i );
       
   930 
       
   931         MUS_LOG1( "mus: [ENGINE]     Current audio element set to : %d ", i )
       
   932 
       
   933         // Set up an audio outstream.
       
   934         CMceAudioStream* audioOut = CMceAudioStream::NewLC();
       
   935 
       
   936         CMceRtpSink* rtpSink = CMceRtpSink::NewLC();  
       
   937         audioOut->AddSinkL( rtpSink );
       
   938         CleanupStack::Pop( rtpSink );
       
   939 
       
   940         audioOut->SetSourceL( fileSource );
       
   941 
       
   942         iSession->AddStreamL( audioOut );
       
   943         CleanupStack::Pop( audioOut );
       
   944 
       
   945         MUS_LOG( "mus: [ENGINE]     Audio outstream created" )
       
   946 
       
   947         // Set up an audio stream to local speaker
       
   948         audioOut = CMceAudioStream::NewLC();
       
   949         
       
   950         MusEngMceUtils::AddSpeakerL( *audioOut );
       
   951 
       
   952         audioOut->SetSourceL( fileSource );
       
   953 
       
   954         iSession->AddStreamL( audioOut );
       
   955         CleanupStack::Pop( audioOut );
       
   956 
       
   957         MUS_LOG( "mus: [ENGINE]     Local audio stream created" )
       
   958 
       
   959         aLocalBundle.AddStreamL( *audioOut );
       
   960 
       
   961         MUS_LOG( "mus: [ENGINE]     Local audio stream added to bundle" )
       
   962         }
       
   963 
       
   964     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructAudioStructureL()" )
       
   965     }
       
   966 
       
   967 // -----------------------------------------------------------------------------
       
   968 // Calculates how long MCE buffers based on time between buffering and streaming
       
   969 // events. 
       
   970 // -----------------------------------------------------------------------------
       
   971 //
       
   972 void CMusEngClipSession::DetermineBufferingPeriod( CMceMediaStream& aStream )
       
   973     {
       
   974     MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::DetermineBufferingPeriod()" )
       
   975     
       
   976     // Determine file position modifier from time difference between buffering
       
   977     // and streaming events
       
   978     if ( aStream.State() == CMceMediaStream::EBuffering )
       
   979         {
       
   980         iBufferingStartedTime.HomeTime();
       
   981         }
       
   982     
       
   983     if ( aStream.State() == CMceMediaStream::EStreaming )
       
   984         {
       
   985         if ( iBufferingStartedTime.Int64() != 0 )
       
   986             {
       
   987             TTime currentTime;
       
   988             currentTime.HomeTime();
       
   989             
       
   990             TTimeIntervalMicroSeconds bufferingPeriod = 
       
   991                 currentTime.MicroSecondsFrom( iBufferingStartedTime );
       
   992             
       
   993             const TInt KMusMinimumBufferingPeriod( 500000 );
       
   994             if ( bufferingPeriod > KMusMinimumBufferingPeriod )
       
   995                 {
       
   996                 iBufferingPeriod = bufferingPeriod;
       
   997                 }
       
   998                 
       
   999             MUS_LOG1( "mus: [ENGINE] current buffering period:%d", 
       
  1000                       iBufferingPeriod.Int64() )
       
  1001             
       
  1002             iBufferingStartedTime = 0;
       
  1003             }
       
  1004         }
       
  1005         
       
  1006     MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DetermineBufferingPeriod()" )
       
  1007     }
       
  1008 
       
  1009 // -----------------------------------------------------------------------------
       
  1010 // Modifies file position if position has reached end before clip has ended.
       
  1011 // File position is not going in sync with local video playback as playback
       
  1012 // buffers media before starting playing.
       
  1013 // -----------------------------------------------------------------------------
       
  1014 //
       
  1015 TTimeIntervalMicroSeconds CMusEngClipSession::GetVideoSinkRelativeFilePos( 
       
  1016     const TTimeIntervalMicroSeconds& aActualPosition, 
       
  1017     const TTimeIntervalMicroSeconds& aDuration )
       
  1018     { 
       
  1019     MUS_LOG1( "mus: [ENGINE] PositionMicroSecondsL, pos before mod:%d", 
       
  1020               aActualPosition.Int64() )
       
  1021     
       
  1022     TTimeIntervalMicroSeconds tempCalculatedPosition( aActualPosition );
       
  1023     
       
  1024     if ( iDelayFileEndingPos != 0 )
       
  1025         {
       
  1026         iDelayFileEndingPos = aDuration;
       
  1027         tempCalculatedPosition = iDelayFileEndingPos;
       
  1028         }
       
  1029     else
       
  1030         {
       
  1031         // FRWD can go to zero even if clip has not ended, do not modify 
       
  1032         // time in such situation.
       
  1033         if ( aActualPosition == 0 && 
       
  1034              !iClipEnded && 
       
  1035              iFRWDStartTime.Int64() == 0 && 
       
  1036              !iRewindedToBeginning )
       
  1037             {
       
  1038             const TInt KMusDelayEndingModifier = 2;
       
  1039             iDelayFileEndingPos = aDuration.Int64() - 
       
  1040                 iBufferingPeriod.Int64() / KMusDelayEndingModifier;
       
  1041             tempCalculatedPosition = iDelayFileEndingPos;
       
  1042             if ( iPreviousPos > tempCalculatedPosition )
       
  1043                 {
       
  1044                 tempCalculatedPosition = iPreviousPos;
       
  1045                 }
       
  1046             }
       
  1047         else
       
  1048             {
       
  1049             iDelayFileEndingPos = 0;
       
  1050             }
       
  1051         
       
  1052         if ( iRewindedToBeginning && aActualPosition > 0 )
       
  1053             {
       
  1054             iRewindedToBeginning = EFalse;
       
  1055             }
       
  1056             
       
  1057         if ( tempCalculatedPosition < 0 )
       
  1058             {
       
  1059             tempCalculatedPosition = 0;
       
  1060             }
       
  1061         }
       
  1062     
       
  1063     iPreviousPos = tempCalculatedPosition;
       
  1064             
       
  1065     return tempCalculatedPosition;
       
  1066     }
       
  1067 
       
  1068 // -----------------------------------------------------------------------------
       
  1069 //
       
  1070 // -----------------------------------------------------------------------------
       
  1071 //
       
  1072 TBool CMusEngClipSession::IsH264Supported() const
       
  1073     {
       
  1074     return ( iVideoCodecList && iVideoCodecList->FindF( KMceSDPNameH264() ) >= 0 );
       
  1075     }
       
  1076     
       
  1077 // End of file
       
  1078