camcordermmfplugin/mediarecorder/Src/CCMRMDFVideoRecorder.cpp
changeset 0 9b3e960ffc8a
child 1 2d3e1993fb02
equal deleted inserted replaced
-1:000000000000 0:9b3e960ffc8a
       
     1 /*
       
     2 * Copyright (c) 2002-2008 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:  Implementation for video recorder
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "mmf/common/mmfbase.h"
       
    21 #include "CCMRRecorderBase.h"
       
    22 #include "CCMRVideoSettings.h"      // default video settings
       
    23 #include "CCMRSupportedCodecs.h"
       
    24 #include "CCMRVideoHWParams.h"
       
    25 #include "CCMRVideoRecorder.h"
       
    26 #include "CCMRMediaRecorder.h"      // for bitrate control mode
       
    27 #include "CCMRVideoThreadProxy.h"
       
    28 #include "CCMRFifo.h"
       
    29 #include "CCMRActiveOutput.h"
       
    30 #include "CCMRVideoCodecDataH263.h"
       
    31 #include "CCMRVideoCodecDataMPEG4.h"
       
    32 #include "CCMRVideoCodecDataH264AVC.h"
       
    33 #include <mmf/common/mmfvideo.h>
       
    34 
       
    35 /*
       
    36 #include "OstTraceDefinitions.h"
       
    37 #ifdef OST_TRACE_COMPILER_IN_USE
       
    38 #include "CCMRMDFVideoRecorderTraces.h"
       
    39 #endif
       
    40 */
       
    41 
       
    42 // MACROS
       
    43 // Assertion macro wrapper for code cleanup
       
    44 #define VRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CCMRMDFVIDEORECORDER"), EInternalAssertionFailure))
       
    45 
       
    46 // Debug print macro
       
    47 #ifdef _DEBUG
       
    48 #include <e32svr.h>
       
    49 #define PRINT(x) RDebug::Print x;
       
    50 #else
       
    51 #define PRINT(x)
       
    52 #endif
       
    53 
       
    54 // ============================= LOCAL FUNCTIONS ===============================
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // convertFrameRateToInterval Converts framerate to frame time interval
       
    58 // (time between 2 consecutive frames).
       
    59 // Returns: TInt time between 2 consecutive frames
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 static TInt convertFrameRateToInterval(TReal32 aFrameRate)
       
    63     {
       
    64     return (TInt(1E6/aFrameRate + 0.5));
       
    65     }
       
    66 
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // convertFrameRateToInterval Converts framerate to frame time interval
       
    70 // (time between 2 consecutive frames).
       
    71 // Returns: TInt time between 2 consecutive frames
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 static TInt TLinearOrderFuncVideoSizeRate(const TPictureRateAndSize& aPictureRateAndSize1,
       
    75 										  const TPictureRateAndSize& aPictureRateAndSize2 )
       
    76 	{
       
    77 	if ( (aPictureRateAndSize1.iPictureSize.iWidth == aPictureRateAndSize2.iPictureSize.iWidth) &&
       
    78 		 (aPictureRateAndSize1.iPictureSize.iHeight == aPictureRateAndSize2.iPictureSize.iHeight) &&
       
    79 		 (aPictureRateAndSize1.iPictureRate == aPictureRateAndSize2.iPictureRate) )
       
    80 		{
       
    81 		return 0;
       
    82 		}
       
    83 
       
    84 	if ( (aPictureRateAndSize1.iPictureSize.iWidth < aPictureRateAndSize2.iPictureSize.iWidth) ||
       
    85 		 (aPictureRateAndSize1.iPictureSize.iHeight < aPictureRateAndSize2.iPictureSize.iHeight) ||
       
    86 		 (aPictureRateAndSize1.iPictureRate < aPictureRateAndSize2.iPictureRate))
       
    87 		{
       
    88 		return -1;
       
    89 		}
       
    90 	else
       
    91 		{
       
    92 		return 1;
       
    93 		}
       
    94 	}
       
    95 
       
    96 // ================= MEMBER FUNCTIONS =======================
       
    97 
       
    98 // ---------------------------------------------------------
       
    99 // CCMRVideoRecorder::NewL
       
   100 // Two-phased constructor.
       
   101 // ---------------------------------------------------------
       
   102 //
       
   103 CCMRVideoRecorder* CCMRVideoRecorder::NewL(MAsyncEventHandler& aEventHandler, CCMRConfigManager* aConfig )
       
   104     {
       
   105     PRINT((_L("CCMRVideoRecorder::NewL(), In: MDF")))
       
   106 
       
   107     CCMRVideoRecorder* self = new (ELeave) CCMRVideoRecorder(aEventHandler);
       
   108     CleanupStack::PushL( self );
       
   109     self->ConstructL(aConfig);
       
   110     CleanupStack::Pop();
       
   111 
       
   112     PRINT((_L("CCMRVideoRecorder::NewL(), Out: MDF")))
       
   113     return self;
       
   114     }
       
   115 
       
   116 
       
   117 // ---------------------------------------------------------
       
   118 // CCMRVideoRecorder::ConstructL()
       
   119 // Symbian 2nd phase constructor can leave.
       
   120 // ---------------------------------------------------------
       
   121 //
       
   122 void CCMRVideoRecorder::ConstructL(CCMRConfigManager* aConfig)
       
   123     {
       
   124     PRINT((_L("CCMRVideoRecorder::ConstructL(), In")))
       
   125 
       
   126     SetState(EStateNone);
       
   127 
       
   128     iConfig = aConfig;
       
   129     iNumCameraBuffers = iConfig->PluginSettings().iCMRNumCameraBuffers;
       
   130     // Create input fifo
       
   131     iSourceFifo = CCMRFifo::NewL(iNumCameraBuffers);
       
   132     iCodingFifo = CCMRFifo::NewL(iNumCameraBuffers);
       
   133 
       
   134     iOutputSinkBuffer = new (ELeave) CCMRMediaBuffer;
       
   135 
       
   136     iSizeIndex = -1;
       
   137     iSizeIndex420 = -1;
       
   138     iSizeIndex422 = -1;
       
   139     iSizeIndexDCEncoder = -1;
       
   140     iRateIndex = -1;
       
   141     iRateIndex420 = -1;
       
   142     iRateIndex422 = -1;
       
   143     iRateIndexDCEncoder = -1;
       
   144     iDevVideoRec = NULL;
       
   145     iEncoderHWDeviceId = 0;
       
   146     iPreProcessorHWDeviceId = 0;
       
   147     iOutputVideoBuffer = NULL;
       
   148     iVideoBufferType = CCMRMediaBuffer::EVideoH263;
       
   149     iClockSource = NULL;
       
   150     iDecSpecInfoLength = 0;
       
   151     iPreferredEncoderUID = KNullUid;
       
   152     iPreferredEncapsulationSet = EFalse;
       
   153     iFrameSize.SetSize( KCMRFrameWidth, KCMRFrameHeight );
       
   154     iSourceFrameRate = KCMRFrameRate;
       
   155     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
   156     iEncodingFrameRate = KCMRFrameRate;
       
   157     iMaxFrameRate4GivenSize = KCMRFrameRate;
       
   158     iRequestedFrameRate = KCMRFrameRate;
       
   159     CCMRRecorderBase::SetTargetBitRateL( KCMRTargetBitRate );
       
   160 
       
   161     iMinRandomAccessPeriodInSeconds = KCMRMinRandomAccessPeriod;
       
   162 
       
   163     iMimeType = KCMRMimeTypeH263BaselineProfile;    //copy
       
   164     iMimeType += _L8( "; level=10" );    // append
       
   165     iVideoCodecData = new (ELeave) CCMRVideoCodecDataH263(10);    // default is H.263 level 10
       
   166 
       
   167     iBitRateMode = EBitRateConstant;
       
   168 
       
   169     iTimeWhenPaused = 0;
       
   170     iTotalPausedTime = 0;
       
   171 
       
   172     iErrorCode = KErrNone;
       
   173 
       
   174     iEncoderInputQueueLength = 0;
       
   175 
       
   176     iNumberOfCapturedFrames = 0;
       
   177     iNumberOfEncodedFrames = 0;
       
   178 
       
   179     iMutexObj.CreateLocal();
       
   180     iMutexCreated = ETrue;
       
   181     iBufferReturnAO = CCMRReturnAO::NewL(this);
       
   182 
       
   183     iFatalError = EFalse;
       
   184     iInputEnd = EFalse;
       
   185     iStreamEnd = EFalse;
       
   186 
       
   187     // Direct capture
       
   188     iDirectCapture = EFalse;
       
   189     iCameraHandle = 0;
       
   190     iSkipBuffers = EFalse;
       
   191     iDriftFrameSkipCount = 0;
       
   192     iAddedFrameDurationCount = 0;
       
   193     iPreviousCameraFrameIndex = 0;
       
   194 
       
   195 #ifdef _DEBUG
       
   196     iLastCapture = 0;
       
   197     iCumulativeEncodingTime = iCumulativeCaptureTime = 0;
       
   198     iAverageEncodingTime = iAverageCaptureTime = 0;
       
   199 #endif
       
   200 	iDevVideoRec = CMMFDevVideoRecord::NewL( *this );
       
   201 	iAvailableVideoEncoders.Reset();
       
   202 	iAvailableVideoFrameSizesRates.Reset();
       
   203 
       
   204 	PRINT((_L("CCMRVideoRecorder::ConstructL() looking for defaul video codec encoder(s)")));
       
   205 	iDevVideoRec->FindEncodersL(iMimeType, 0 /* aPreProc */, iAvailableVideoEncoders, EFalse );
       
   206 	PRINT((_L("CCMRVideoRecorder::ConstructL() search found %d encoder(s)"), iAvailableVideoEncoders.Count() ));
       
   207 
       
   208 	if ( iConfig )
       
   209 		{
       
   210 		iConfig->SetVideoCodec(iMimeType);
       
   211 		iConfig->SetVideoPixelAspectRatio(KCMRAspectRatioNum, KCMRAspectRatioDenom);
       
   212 
       
   213 		// fill out defaults for Rate Control from ICM.
       
   214 	    iRateControlOptions.iPictureQuality = iConfig->PluginSettings().iCMRPictureQuality;
       
   215 	    iRateControlOptions.iLatencyQualityTradeoff = iConfig->PluginSettings().iCMRLatencyQualityTradeoff; // latency vs. quality
       
   216 	    iRateControlOptions.iQualityTemporalTradeoff = iConfig->PluginSettings().iCMRQualityTemporalTradeoff; // spatial vs. temporal quality
       
   217 		}
       
   218     UpdateSupportedVideoFrameSizesRates();
       
   219     PRINT((_L("CCMRVideoRecorder::ConstructL(), Out")))
       
   220     }
       
   221 
       
   222 
       
   223 // ---------------------------------------------------------
       
   224 // CCMRVideoRecorder::~CCMRVideoRecorder()
       
   225 // Destructor
       
   226 // ---------------------------------------------------------
       
   227 //
       
   228 CCMRVideoRecorder::~CCMRVideoRecorder()
       
   229     {
       
   230     PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder(), In")));
       
   231     // This is the counterpart to NewL & OpenL, e.g. Close & Delete
       
   232     // free all memory allocated and uninitalize & delete objects created, e.g. DevVideoRecord
       
   233 
       
   234 #if defined VIDEO_FILE_OUTPUT || defined VIDEO_BS_FILE_OUTPUT
       
   235     iOutputFile.Close();
       
   236     iFs.Close();
       
   237 #endif
       
   238 
       
   239     // to make PC Lint happy
       
   240     iOutputVideoBuffer = NULL;
       
   241     iOutput = NULL;
       
   242     iClockSource = NULL;
       
   243 
       
   244     // delete DevVideoRecord instance
       
   245     delete iDevVideoRec;
       
   246     PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder() devvideorec deleted")));
       
   247 
       
   248     iAvailableVideoFrameSizesRates.Close();
       
   249     iAvailableVideoEncoders.Close();
       
   250 
       
   251     delete iOutputSinkBuffer;
       
   252     iOutputSinkBuffer = NULL;
       
   253 
       
   254     delete iVideoCodecData;
       
   255     iVideoCodecData = NULL;
       
   256 
       
   257     // empty the source fifo, just in case once more; this should be done a) by encoder and b) by MdvroStreamEnd()
       
   258     MFrameBuffer* cbuffer;
       
   259     if ( iSourceFifo )
       
   260         {
       
   261         while ( !iSourceFifo->IsEmpty() )
       
   262             {
       
   263             cbuffer = reinterpret_cast<MFrameBuffer*>(iSourceFifo->Get());
       
   264             // Release camera API buffer
       
   265             cbuffer->Release();
       
   266             }
       
   267         delete iSourceFifo;
       
   268         iSourceFifo = NULL;
       
   269         }
       
   270     TVideoPicture* picture;
       
   271     if ( iCodingFifo )
       
   272         {
       
   273         // delete the empty devvr picture-holders stored in the fifo
       
   274         while ( !iCodingFifo->IsEmpty() )
       
   275             {
       
   276             picture = reinterpret_cast<TVideoPicture*>(iCodingFifo->Get());
       
   277             PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder() deleting %x"),picture));
       
   278             delete picture;
       
   279             }
       
   280         delete iCodingFifo;
       
   281         iCodingFifo = NULL;
       
   282         }
       
   283     PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder() fifos deleted")));
       
   284 
       
   285     if ( iDecSpecInfo )
       
   286         {
       
   287         // We still have MPEG-4 decoder configuration info stored
       
   288         delete iDecSpecInfo;
       
   289         iDecSpecInfo = NULL;
       
   290         }
       
   291 
       
   292     // delete camera
       
   293     delete iSource;
       
   294     iSource = NULL;
       
   295     PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder() camera deleted")));
       
   296 
       
   297     if ( iBufferReturnAO )
       
   298         {
       
   299         iBufferReturnAO->Cancel();
       
   300         delete iBufferReturnAO;
       
   301         }
       
   302 
       
   303     if ( iThreadHandleOpened )
       
   304         {
       
   305         iOutputThreadHandle.Close();
       
   306         iThreadHandleOpened = EFalse;
       
   307         }
       
   308 
       
   309     if ( iMutexCreated )
       
   310         {
       
   311         iMutexObj.Close();
       
   312         }
       
   313 
       
   314     SetState(EStateNone);
       
   315 
       
   316     PRINT((_L("CCMRVideoRecorder::~CCMRVideoRecorder(), Out")));
       
   317     }
       
   318 
       
   319 
       
   320 // ---------------------------------------------------------
       
   321 // CCMRVideoRecorder::SetOutputL
       
   322 // Sets output active object
       
   323 // (other items were commented in a header).
       
   324 // ---------------------------------------------------------
       
   325 //
       
   326 void CCMRVideoRecorder::SetOutputL(CCMRActiveOutput* aOutput)
       
   327     {
       
   328     iOutput = aOutput;
       
   329     iOutput->RegisterSourceL( this );
       
   330     if ( iSource && iThreadHandleOpened )
       
   331         {
       
   332         SetState( EStateOpen );
       
   333         }
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------
       
   337 // CCMRVideoRecorder::SetClockSourceL
       
   338 // Set clock source
       
   339 // (other items were commented in a header).
       
   340 // ---------------------------------------------------------
       
   341 //
       
   342 void CCMRVideoRecorder::SetClockSource(MMMFClockSource* aClockSource)
       
   343     {
       
   344     iClockSource = aClockSource;
       
   345     }
       
   346 
       
   347 // ---------------------------------------------------------
       
   348 // CCMRVideoRecorder::SetOutputThreadIdL
       
   349 // Sets id of the output thread
       
   350 // (other items were commented in a header).
       
   351 // ---------------------------------------------------------
       
   352 //
       
   353 void CCMRVideoRecorder::SetOutputThreadIdL(TUint aThreadId)
       
   354     {
       
   355     User::LeaveIfError( iOutputThreadHandle.Open(aThreadId) );
       
   356 
       
   357     iThreadHandleOpened = ETrue;
       
   358     if ( iOutput && iSource )
       
   359         {
       
   360         SetState( EStateOpen );
       
   361         }
       
   362     }
       
   363 
       
   364 
       
   365 // ---------------------------------------------------------
       
   366 // CCMRVideoRecorder::SetCameraHandleL
       
   367 // Sets camera handle and creates camera instance
       
   368 // (other items were commented in a header).
       
   369 // ---------------------------------------------------------
       
   370 //
       
   371 void CCMRVideoRecorder::SetCameraHandleL(TInt aCameraHandle)
       
   372     {
       
   373     PRINT((_L("CCMRVideoRecorder::SetCameraHandleL(), In")))
       
   374 
       
   375     // Create video source
       
   376 #ifdef VIDEO_FILE_INPUT
       
   377     iSource = CCMRVideoFileSource::NewL(this);
       
   378 #else
       
   379     iSource = CCMRVideoCameraSource::NewL(this, aCameraHandle);
       
   380 #endif
       
   381 
       
   382     // Store a camera handle for future use
       
   383     iCameraHandle = aCameraHandle;
       
   384 
       
   385     // get camera info
       
   386     iSource->CameraInfo(iCameraInfo);
       
   387 
       
   388 #if defined VIDEO_FILE_OUTPUT || defined VIDEO_BS_FILE_OUTPUT
       
   389     User::LeaveIfError(iFs.Connect());
       
   390     User::LeaveIfError(iOutputFile.Replace(iFs, _L("videorec_out.bin"), EFileWrite | EFileShareExclusive));
       
   391 #endif
       
   392 
       
   393     if ( iOutput && iThreadHandleOpened )
       
   394         {
       
   395         SetState( EStateOpen );
       
   396         }
       
   397 
       
   398     PRINT((_L("CCMRVideoRecorder::SetCameraHandleL(), Out")))
       
   399     }
       
   400 
       
   401 // ---------------------------------------------------------
       
   402 // CCMRVideoRecorder::SetupEncoderL
       
   403 // Private helper method to select & setup the encoder
       
   404 // plugin devvr must use
       
   405 // (other items were commented in a header).
       
   406 // ---------------------------------------------------------
       
   407 //
       
   408 void CCMRVideoRecorder::SetupEncoderL()
       
   409     {
       
   410 #ifdef _DEBUG
       
   411     TBuf<256> mime;
       
   412     mime.Copy(iMimeType);
       
   413     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() in, video mime-type: %S "), &mime ));
       
   414 #endif
       
   415 
       
   416     if ( iPreferredEncoderUID != KNullUid )
       
   417         {// We have preferred encoder UID from client - override encoder search and use it instead.
       
   418         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() skipping encoder search. Using API user encoder: %d "), iPreferredEncoderUID.iUid));
       
   419         iAvailableVideoEncoders.Reset();
       
   420         iAvailableVideoEncoders.AppendL(iPreferredEncoderUID);
       
   421         }
       
   422     else if ( iConfig &&
       
   423             ( iConfig->IsICMConfigDataAvailable() ) &&
       
   424             ( iConfig->VideoQualitySettings().iVideoEncoderUID != KNullUid ) )
       
   425         {// Video quality set has set UID value - override encoder search and use it instead.
       
   426         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() skipping encoder search. Using ICM config encoder: %d "), iPreferredEncoderUID.iUid));
       
   427         iAvailableVideoEncoders.Reset();
       
   428         iAvailableVideoEncoders.AppendL(iPreferredEncoderUID);
       
   429         }
       
   430 
       
   431     // uncompressed format structures for YUV420 planar
       
   432     TBool cameraSupports420 = ETrue;
       
   433 
       
   434     if ( (iSizeIndex420 < 0) || (iRateIndex420 < 0) )
       
   435         {
       
   436         cameraSupports420 = EFalse;
       
   437         }
       
   438     else
       
   439         {
       
   440         cameraSupports420 = ETrue;
       
   441         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() camera supports YUV420 planar") ));
       
   442         }
       
   443 
       
   444     // uncompressed format structures for YUV422
       
   445     TBool cameraSupports422 = ETrue;
       
   446     if ( (iSizeIndex422 < 0) || (iRateIndex422 < 0) )
       
   447         {
       
   448         cameraSupports422 = EFalse;
       
   449         }
       
   450     else
       
   451         {
       
   452         cameraSupports422 = ETrue;
       
   453         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() camera supports YUV422 interleaved") ));
       
   454         }
       
   455 
       
   456     // Output format
       
   457     CCompressedVideoFormat *comprFormat = CCompressedVideoFormat::NewL( iMimeType );
       
   458     CleanupStack::PushL( comprFormat );
       
   459 
       
   460     // index for encoder candidate. Have to go through the list to find an accerated encoder
       
   461     TInt encoderIndex = -1;
       
   462     TUncompressedVideoFormat encoderUncompFormat;
       
   463 
       
   464     // encoder info for retrieving capabilities
       
   465     CVideoEncoderInfo* encoderInfo = NULL;
       
   466 
       
   467     // this is needed if init of HW accelerated codec failed and we retry => forces to select ARM codec
       
   468     TBool alreadyFailedWithHWAccelerated = iVideoCodecHWAccelerated;
       
   469     iVideoCodecHWAccelerated = EFalse;
       
   470 
       
   471     TInt infoError = KErrNone;
       
   472     TBool encoderSupports422 = EFalse;
       
   473     TBool encoderSupports420 = EFalse;
       
   474 
       
   475     TYuvCoefficients preproInputYuvCoefficient;
       
   476     TYuvCoefficients preproOutputYuvCoefficient;
       
   477     TYuvCoefficients encoderInputYuvCoefficient;
       
   478     TUint aspectRatioNum = 0;
       
   479     TUint aspectRatioDenom = 0;
       
   480     TVideoDataUnitEncapsulation outputFormatEncapsulation = EDuElementaryStream;
       
   481 
       
   482     if( KCMRMimeTypeH263() == iMimeType.Left( KCMRMimeTypeH263().Length() ))
       
   483         {// H.263
       
   484         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - setting H.263 YUVs") ));
       
   485         preproInputYuvCoefficient = EYuvBt601Range1;
       
   486         preproOutputYuvCoefficient = EYuvBt601Range0;
       
   487         encoderInputYuvCoefficient = EYuvBt601Range0;
       
   488         iVideoBufferType = CCMRMediaBuffer::EVideoH263;
       
   489         // pixel aspect ratios
       
   490         if ( iConfig && iConfig->IsICMConfigDataAvailable() )
       
   491 	        {
       
   492 	        aspectRatioNum = iConfig->VideoQualitySettings().iVideoPixelAspectRatioNum;
       
   493 	        aspectRatioDenom = iConfig->VideoQualitySettings().iVideoPixelAspectRatioDenom;
       
   494 	        }
       
   495         else
       
   496 	        {
       
   497 	        aspectRatioNum = KCMRAspectRatioNum;
       
   498 	        aspectRatioDenom = KCMRAspectRatioDenom;
       
   499 	        }
       
   500         }
       
   501     else if ( KCMRMimeTypeMPEG4V() == iMimeType.Left( KCMRMimeTypeMPEG4V().Length() ))
       
   502         {// MPEG-4
       
   503         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - setting MPEG4 YUVs") ));
       
   504         preproInputYuvCoefficient = EYuvBt709Range1;
       
   505         preproOutputYuvCoefficient = EYuvBt709Range1;
       
   506         encoderInputYuvCoefficient = EYuvBt709Range1;
       
   507         // pixel aspect ratios
       
   508         if ( iConfig && iConfig->IsICMConfigDataAvailable() )
       
   509 	        {
       
   510 	        aspectRatioNum = iConfig->VideoQualitySettings().iVideoPixelAspectRatioNum;
       
   511 	        aspectRatioDenom = iConfig->VideoQualitySettings().iVideoPixelAspectRatioDenom;
       
   512 	        }
       
   513         else
       
   514 	        {
       
   515 	        aspectRatioNum = KCMRMPEG4AspectRatioNum;
       
   516 	        aspectRatioDenom = KCMRMPEG4AspectRatioDenom;
       
   517 	        }
       
   518         iVideoBufferType = CCMRMediaBuffer::EVideoMPEG4;
       
   519         }
       
   520     else
       
   521         {// H.264 AVC
       
   522         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - setting H.264 AVC YUVs") ));
       
   523         preproInputYuvCoefficient = EYuvBt709Range1;
       
   524         preproOutputYuvCoefficient = EYuvBt709Range1;
       
   525         encoderInputYuvCoefficient = EYuvBt709Range1;
       
   526         // pixel aspect ratios 1:1
       
   527         if ( iConfig && iConfig->IsICMConfigDataAvailable() )
       
   528 	        {
       
   529 	        aspectRatioNum = iConfig->VideoQualitySettings().iVideoPixelAspectRatioNum;
       
   530 	        aspectRatioDenom = iConfig->VideoQualitySettings().iVideoPixelAspectRatioDenom;
       
   531 	        }
       
   532         else
       
   533 	        {
       
   534 	        aspectRatioNum = KCMRMPEG4AspectRatioNum;
       
   535 	        aspectRatioDenom = KCMRMPEG4AspectRatioDenom;
       
   536 	        }
       
   537         // output format encapsulation
       
   538         iVideoBufferType = CCMRMediaBuffer::EVideoH264NAL;
       
   539         outputFormatEncapsulation = EDuGenericPayload;
       
   540         }
       
   541 
       
   542     TBool directCaptureEncoder = EFalse;
       
   543     TInt supportedEncoderInputsCount = 0;
       
   544     // find an encoder with matching capabilities
       
   545     for ( TInt i = 0 ; i < iAvailableVideoEncoders.Count(); i++ )
       
   546         {
       
   547         encoderInfo = NULL;
       
   548         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - getting info from a plugin index[%d] with Uid 0x%x"), i, iAvailableVideoEncoders[i].iUid ));
       
   549         TRAPD(error, (encoderInfo = ReadEncoderInfoL(iAvailableVideoEncoders[i])) );
       
   550 
       
   551         if ( encoderInfo == NULL )
       
   552             {
       
   553             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - getting info from a plugin failed, skipping") ));
       
   554             infoError = error;
       
   555             }
       
   556         else
       
   557             {
       
   558             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - got an info from a plugin, checking...") ));
       
   559 
       
   560             // item was popped in CheckEncoderInfoL, push it back to stack
       
   561             CleanupStack::PushL( encoderInfo );
       
   562 
       
   563             // check if compressed video format matches
       
   564             if ( encoderInfo->SupportsOutputFormat(*comprFormat) )   // max picture size & bit-rate was checked in the level of comprFormat
       
   565                 {
       
   566                 // check input format of encoder.
       
   567                 // a candidate encoder supporting the required compressed format was found
       
   568                 encoderSupports422 = EFalse;
       
   569                 encoderSupports420 = EFalse;
       
   570 
       
   571                 RArray<TUncompressedVideoFormat> supportedEncoderInputs = encoderInfo->SupportedInputFormats();
       
   572                 supportedEncoderInputsCount = supportedEncoderInputs.Count();
       
   573                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Encoder at index[%d] supports %d input format(s), checking for support"), i, supportedEncoderInputs.Count() ));
       
   574 
       
   575                 // Go through supported input format and look for match to important parameters.
       
   576                 for(TInt j = 0; j < supportedEncoderInputsCount; j++ )
       
   577                     {
       
   578                     if ( !encoderSupports422 &&
       
   579                          cameraSupports422 &&
       
   580                          supportedEncoderInputs[j].iDataFormat == EYuvRawData &&
       
   581                          supportedEncoderInputs[j].iYuvFormat.iCoefficients == encoderInputYuvCoefficient &&
       
   582                          ( supportedEncoderInputs[j].iYuvFormat.iDataLayout == EYuvDataInterleavedLE ||
       
   583                            supportedEncoderInputs[j].iYuvFormat.iDataLayout == EYuvDataInterleavedBE ) &&
       
   584                          supportedEncoderInputs[j].iYuvFormat.iYuv2RgbMatrix == NULL &&
       
   585                          supportedEncoderInputs[j].iYuvFormat.iRgb2YuvMatrix == NULL &&
       
   586                          supportedEncoderInputs[j].iYuvFormat.iAspectRatioNum ==  aspectRatioNum &&
       
   587                          supportedEncoderInputs[j].iYuvFormat.iAspectRatioDenom ==  aspectRatioDenom &&
       
   588                          ( supportedEncoderInputs[j].iYuvFormat.iPattern == EYuv422Chroma1 ||
       
   589                          supportedEncoderInputs[j].iYuvFormat.iPattern == EYuv422Chroma2 ) )
       
   590                         {
       
   591                         // YUV 422 input format can be used with this encoder
       
   592                         encoderSupports422 = ETrue;
       
   593                         encoderUncompFormat = supportedEncoderInputs[j];
       
   594                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Encoder at index[%d] supports YUV422 interleaved"), i ));
       
   595                         break;
       
   596                         }
       
   597                     if ( !encoderSupports420 &&
       
   598                          !encoderSupports422 &&
       
   599                          cameraSupports420 &&
       
   600                          supportedEncoderInputs[j].iDataFormat == EYuvRawData &&
       
   601                          supportedEncoderInputs[j].iYuvFormat.iCoefficients == encoderInputYuvCoefficient &&
       
   602                          supportedEncoderInputs[j].iYuvFormat.iDataLayout == EYuvDataPlanar &&
       
   603                          supportedEncoderInputs[j].iYuvFormat.iYuv2RgbMatrix == NULL &&
       
   604                          supportedEncoderInputs[j].iYuvFormat.iRgb2YuvMatrix == NULL &&
       
   605                          supportedEncoderInputs[j].iYuvFormat.iAspectRatioNum ==  aspectRatioNum &&
       
   606                          supportedEncoderInputs[j].iYuvFormat.iAspectRatioDenom ==  aspectRatioDenom &&
       
   607                          ( supportedEncoderInputs[j].iYuvFormat.iPattern == EYuv420Chroma1 ||
       
   608                            supportedEncoderInputs[j].iYuvFormat.iPattern == EYuv420Chroma2 ) )
       
   609                         {
       
   610                         // YUV 420 planar input format can be used with this encoder
       
   611                         encoderSupports420 = ETrue;
       
   612                         encoderUncompFormat = supportedEncoderInputs[j];
       
   613                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Encoder at index[%d] supports YUV420 planar"), i ));
       
   614                         if( !cameraSupports422 )
       
   615                             {
       
   616                             break;
       
   617                             }
       
   618                         }
       
   619                     }
       
   620                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Encoder at index[%d] supports: 420[%d], 422[%d]"), i, encoderSupports420, encoderSupports422 ));
       
   621 
       
   622                 // Check directCapture support for current codec
       
   623                 directCaptureEncoder = encoderInfo->SupportsDirectCapture();
       
   624                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Encoder at index[%d] supports DirectCapture:[%d]."), i, directCaptureEncoder));
       
   625 
       
   626                 // determine H.264 AVC encapsulation
       
   627                 if ( (iVideoBufferType == CCMRMediaBuffer::EVideoH264NAL) ||
       
   628                      (iVideoBufferType == CCMRMediaBuffer::EVideoH264Bytestream) )
       
   629                     {
       
   630                     if (( iPreferredEncapsulationSet ) &&
       
   631                         ( encoderInfo->SupportedDataUnitEncapsulations() & iPreferredEncapsulation ))
       
   632                         {
       
   633                         outputFormatEncapsulation = iPreferredEncapsulation;
       
   634                         }
       
   635                     else
       
   636                         {
       
   637                         if (encoderInfo->SupportedDataUnitEncapsulations() & EDuGenericPayload)
       
   638                             {
       
   639                             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() H.264 Encoder at index[%d] set to EDuGenericPayload encapsulation."), i));
       
   640                             outputFormatEncapsulation = EDuGenericPayload;
       
   641                             }
       
   642                         else
       
   643                             {
       
   644                             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() H.264 Encoder at index[%d] set to EDuElementaryStream encapsulation."), i));
       
   645                             outputFormatEncapsulation = EDuElementaryStream;
       
   646                             }
       
   647                         }
       
   648 
       
   649                     if ( outputFormatEncapsulation == EDuGenericPayload )
       
   650                         {
       
   651                         iVideoBufferType = CCMRMediaBuffer::EVideoH264NAL;
       
   652                         }
       
   653                     else
       
   654                         {
       
   655                         iVideoBufferType = CCMRMediaBuffer::EVideoH264Bytestream;
       
   656                         }
       
   657                     }
       
   658 
       
   659                 if (directCaptureEncoder && (supportedEncoderInputsCount != 0))
       
   660                     {
       
   661                     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Warning - Encoder at index[%d] publish input formats even though it supports directcapture - ERROR!."), i));
       
   662                     }
       
   663 
       
   664                 if ( encoderSupports422 || encoderSupports420 || (directCaptureEncoder && (supportedEncoderInputsCount == 0)) )
       
   665                     {
       
   666                     // encoder's input format matches with camera's output
       
   667                     if ( encoderInfo->Accelerated() && (alreadyFailedWithHWAccelerated == EFalse) )
       
   668                         // assume there is only 1 HW accelerated codec, and if it was selected previously we come here only if the init failed
       
   669                         // => must use non-hw-accelerated codec
       
   670                         {
       
   671                         // no need to search for more, accelerated encoder is preferred
       
   672                         encoderIndex = i;
       
   673                         iVideoCodecHWAccelerated = ETrue;
       
   674                         iDirectCapture = directCaptureEncoder;
       
   675                         // HW accelerated is preferred regardless of the input format, but if both formats are supported, then 422 is preferred
       
   676                         // need to set the camera variables accordingly
       
   677                         if ( !(directCaptureEncoder && (supportedEncoderInputsCount == 0)) )
       
   678                             {
       
   679                             if ( encoderSupports422 )
       
   680                                 {
       
   681                                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() YUV422 interleaved selected as input format") ));
       
   682                                 iSizeIndex = iSizeIndex422;
       
   683                                 iRateIndex = iRateIndex422;
       
   684                                 iVideoFormat = CCamera::EFormatYUV422;
       
   685                                 }
       
   686                             else if (encoderSupports420)
       
   687                                 {
       
   688                                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() YUV420 planar selected as input format") ));
       
   689                                 iSizeIndex = iSizeIndex420;
       
   690                                 iRateIndex = iRateIndex420;
       
   691                                 iVideoFormat = CCamera::EFormatYUV420Planar;
       
   692                                 }
       
   693                             }
       
   694                         // check max framerate for given picture size
       
   695                         RArray<TPictureRateAndSize> rateAndSize = encoderInfo->MaxPictureRates();
       
   696                         TUint rates = rateAndSize.Count();
       
   697                         for ( TUint j = 0; j < rates; j++ )
       
   698                             {
       
   699                             if ( rateAndSize[j].iPictureSize == iFrameSize )
       
   700                                 {
       
   701                                 iMaxFrameRate4GivenSize = rateAndSize[j].iPictureRate;
       
   702                                 break;
       
   703                                 }
       
   704                             }
       
   705                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - there is a suitable HW accelerated plugin, don't check other plugins") ));
       
   706                         CleanupStack::PopAndDestroy( encoderInfo );
       
   707                         break;
       
   708                         }
       
   709                     else if ( encoderIndex < 0 )
       
   710                         {
       
   711                         // accept also non-accelerated if no other is available
       
   712                         encoderIndex = i;
       
   713                         // encoder is selected regardless of the input format, but if both formats are supported, then 422 is preferred
       
   714                         // need to set the camera variables accordingly
       
   715                         if ( !(directCaptureEncoder && (supportedEncoderInputsCount == 0)) )
       
   716                             {
       
   717                             if ( encoderSupports422 )
       
   718                                 {
       
   719                                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() YUV422 interleaved selected as input format") ));
       
   720                                 iSizeIndex = iSizeIndex422;
       
   721                                 iRateIndex = iRateIndex422;
       
   722                                 iVideoFormat = CCamera::EFormatYUV422;
       
   723                                 }
       
   724                             else if (encoderSupports420)
       
   725                                 {
       
   726                                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() YUV420 planar selected as input format") ));
       
   727                                 iSizeIndex = iSizeIndex420;
       
   728                                 iRateIndex = iRateIndex420;
       
   729                                 iVideoFormat = CCamera::EFormatYUV420Planar;
       
   730                                 }
       
   731                             }
       
   732 
       
   733                         // check max framerate for given picture size
       
   734                         RArray<TPictureRateAndSize> rateAndSize = encoderInfo->MaxPictureRates();
       
   735                         TUint rates = rateAndSize.Count();
       
   736 
       
   737                         for ( TUint j = 0; j < rates; j++ )
       
   738                             {
       
   739                             if ( rateAndSize[j].iPictureSize == iFrameSize )
       
   740                                 {
       
   741                                 iMaxFrameRate4GivenSize = rateAndSize[j].iPictureRate;
       
   742                                 break;
       
   743                                 }
       
   744                             }
       
   745                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - there is a suitable SW plugin.") ));
       
   746                         }
       
   747                     else
       
   748                         {
       
   749                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - there is already similar encoder - preferring first.") ));
       
   750                         // this kind of encoder already found
       
   751                         }
       
   752 
       
   753                     }
       
   754                 else
       
   755                     {
       
   756                     // skip this encoder, done in the following lines
       
   757                     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() encoder doesn't support YUV420/YUV422 input format or isn't directcapture encoder") ));
       
   758                     }
       
   759                 }
       
   760             else
       
   761                 {
       
   762                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() encoder at index[%d] doesn't support given compressed output format"), i ));
       
   763                 }
       
   764             CleanupStack::PopAndDestroy( encoderInfo );
       
   765             }
       
   766         }
       
   767 
       
   768     TUncompressedVideoFormat preproInputFormat = encoderUncompFormat;
       
   769     TUncompressedVideoFormat preproOutputFormat = encoderUncompFormat;
       
   770     preproInputFormat.iYuvFormat.iCoefficients = preproInputYuvCoefficient;
       
   771     preproOutputFormat.iYuvFormat.iCoefficients = preproOutputYuvCoefficient;
       
   772 
       
   773     if ( encoderIndex >= 0 )
       
   774         {
       
   775         if ( iVideoCodecHWAccelerated )
       
   776             {
       
   777             iNumCameraBuffers = iConfig->PluginSettings().iCMRNumCameraBuffers;
       
   778             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - found a suitable HW accelerated video encoder")));
       
   779             }
       
   780         else
       
   781             {
       
   782             iNumCameraBuffers = iConfig->PluginSettings().iCMRNumCameraBuffersARM;
       
   783             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() - found a suitable ARM video encoder")));
       
   784             }
       
   785 
       
   786         // if encoder doesn´t support directcapture try to find preprocessor that does.
       
   787         if ( !iDirectCapture && iVideoCodecHWAccelerated )
       
   788             {
       
   789             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Searching preprocessor.")));
       
   790             RArray<TUid> preprocessors;
       
   791             CleanupClosePushL( preprocessors );
       
   792             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Search starting")));
       
   793 
       
   794             TInt preproSearchErr = KErrNone;
       
   795             TRAP(preproSearchErr, iDevVideoRec->FindPreProcessorsL(EPpYuvToYuv, preprocessors));
       
   796             if (preproSearchErr == KErrNone)
       
   797                 {
       
   798                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Search found %d preprocessor(s)"), preprocessors.Count() ));
       
   799                 CPreProcessorInfo* preprocessorInfo = NULL;
       
   800                 // find a preprocessor with matching capabilities to encoder
       
   801                 for ( TInt k = 0; k < preprocessors.Count(); k++ )
       
   802                     {
       
   803                     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Checking preprocessor at index[%d] with Uid 0x%x"), k, preprocessors[k].iUid ));
       
   804                     preprocessorInfo = iDevVideoRec->PreProcessorInfoLC(preprocessors[k]);
       
   805 
       
   806                     if ( preprocessorInfo->SupportsInputFormat(preproInputFormat) &&
       
   807                          preprocessorInfo->SupportsOutputFormat(preproOutputFormat) &&
       
   808                          preprocessorInfo->SupportsDirectCapture() )
       
   809                         {
       
   810                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() preprocessor[%d] is suitable, setting it as preprocessor"), k ));
       
   811                         iDirectCapture = ETrue;
       
   812                         iPreProcessorHWDeviceId = iDevVideoRec->SelectPreProcessorL(preprocessors[k]);
       
   813                         PRINT((_L("CCMRVideoRecorder::SetupEncoderL() preprocessor selected")));
       
   814                         CleanupStack::PopAndDestroy(preprocessorInfo);
       
   815                         break;
       
   816                         }
       
   817                     CleanupStack::PopAndDestroy(preprocessorInfo);
       
   818                     }
       
   819                 }
       
   820             else if (preproSearchErr == KErrNotFound)
       
   821                 {
       
   822                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() didn't find any preprocessors")));
       
   823                 }
       
   824             else
       
   825                 {
       
   826                 PRINT((_L("CCMRVideoRecorder::SetupEncoderL() preprocessors search error: %d"), preproSearchErr));
       
   827                 CleanupStack::PopAndDestroy(); //preprocessors
       
   828                 User::Leave(preproSearchErr);
       
   829                 }
       
   830             CleanupStack::PopAndDestroy(); //preprocessors
       
   831             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Searching preprocessor done.")));
       
   832             }
       
   833         }
       
   834     else
       
   835         {
       
   836         if ( infoError != KErrNone )
       
   837             {
       
   838             // there is an encoder but it can't be used
       
   839             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() there is an encoder but it can't be used - info error=%d"), infoError ));
       
   840             User::Leave( infoError );
       
   841             }
       
   842         else
       
   843             {
       
   844             // No suitable encoder found. This should not be possible if the codec was properly set beforehand
       
   845             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() No suitable encoder found.")));
       
   846             User::Leave( KErrNotSupported );
       
   847             }
       
   848         }
       
   849 
       
   850     iEncoderHWDeviceId = iDevVideoRec->SelectEncoderL(iAvailableVideoEncoders[encoderIndex]);
       
   851     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() encoder selected")));
       
   852 
       
   853     // Set input format only for non-directcapture encoders
       
   854     if ( (directCaptureEncoder && (supportedEncoderInputsCount == 0)) )
       
   855         {
       
   856         // Direct capture encoders should ignore
       
   857         TUncompressedVideoFormat ignoredFormat;
       
   858         iDevVideoRec->SetInputFormatL(iEncoderHWDeviceId, ignoredFormat, iFrameSize);
       
   859         }
       
   860     else
       
   861         {
       
   862         iDevVideoRec->SetInputFormatL(iEncoderHWDeviceId, encoderUncompFormat, iFrameSize);
       
   863         }
       
   864 
       
   865     if ( iPreProcessorHWDeviceId )
       
   866         {
       
   867         iDevVideoRec->SetInputFormatL(iPreProcessorHWDeviceId, preproInputFormat, iFrameSize);
       
   868         }
       
   869 
       
   870     // Buffer options
       
   871     TEncoderBufferOptions bufferOptions;
       
   872     bufferOptions.iHrdVbvParams.Set(NULL, 0);
       
   873     bufferOptions.iHrdVbvSpec = EHrdVbvNone;
       
   874     bufferOptions.iMaxPreEncoderBufferPictures = iConfig->PluginSettings().iCMRNumCameraBuffers;
       
   875     bufferOptions.iMinNumOutputBuffers = iConfig->PluginSettings().iCMRMinNumOutputBuffers;
       
   876 
       
   877     bufferOptions.iMaxCodedSegmentSize =
       
   878         bufferOptions.iMaxOutputBufferSize =
       
   879         bufferOptions.iMaxCodedPictureSize = iVideoCodecData->MaxBufferLength(iFrameSize);
       
   880 
       
   881     iDevVideoRec->SetBufferOptionsL(bufferOptions);
       
   882 
       
   883     // Set output format
       
   884     iDevVideoRec->SetOutputFormatL(iEncoderHWDeviceId, *comprFormat, EDuCodedPicture,
       
   885                                    outputFormatEncapsulation, EFalse /* aSegmentationAllowed */);
       
   886 
       
   887     if( iPreProcessorHWDeviceId)
       
   888     {
       
   889         iDevVideoRec->SetOutputFormatL(iPreProcessorHWDeviceId, preproOutputFormat);
       
   890     }
       
   891 
       
   892     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() MinRandomAccess= %d"), iMinRandomAccessPeriodInSeconds ));
       
   893     if ( iConfig && iConfig->IsICMConfigDataAvailable() )
       
   894         {
       
   895         iMinRandomAccessPeriodInSeconds = iConfig->VideoQualitySettings().iRandomAccessRate;
       
   896         }
       
   897     else
       
   898         {
       
   899         if ( (iFrameSize.iWidth >= KCMRCIFWidth) && (iFrameSize.iHeight >= KCMRCIFHeight) )
       
   900 	        {
       
   901 	        iMinRandomAccessPeriodInSeconds = KCMRMinRandomAccessPeriodHighRes;
       
   902 	        }
       
   903         }
       
   904     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Set to MinRandomAccess= %d"), iMinRandomAccessPeriodInSeconds ));
       
   905 
       
   906     // Set random access in fps
       
   907     if ( iMinRandomAccessPeriodInSeconds > 0 )
       
   908         {
       
   909         iDevVideoRec->SetMinRandomAccessRate( TReal(1) / TReal(iMinRandomAccessPeriodInSeconds) );
       
   910         }
       
   911     else
       
   912         {
       
   913         // there is no concept of disabling random access in MSL, hence use the default
       
   914         iDevVideoRec->SetMinRandomAccessRate( TReal(1) / TReal(KCMRMinRandomAccessPeriod) );
       
   915         }
       
   916 
       
   917     CleanupStack::PopAndDestroy( comprFormat );
       
   918 
       
   919     // set codec specific settings
       
   920     iVideoCodecData->SetPreInitParamsL(iDevVideoRec);
       
   921 
       
   922     if (iDirectCapture)
       
   923         {
       
   924         TInt status = KErrNone;
       
   925         // Set the data source to a camera
       
   926         TRAP( status, iDevVideoRec->SetSourceCameraL( iCameraHandle, TReal(iSourceFrameRate)) );
       
   927 
       
   928         if ( status != KErrNone )
       
   929             {
       
   930             // Probably it's not supported, although directCapture was declared in the hwdevice info.
       
   931             // Leave or to give one more chance to encoder, to use src memory as a source ?
       
   932             // Yes, otherwise User::Leave(status);
       
   933             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() Setting camerasource to MDF failed.")));
       
   934             }
       
   935         else
       
   936             {
       
   937             if ( iClockSource )
       
   938                 {
       
   939                 iDevVideoRec->SetClockSource( iClockSource );
       
   940                 }
       
   941             // Ok, use direct capture
       
   942             PRINT((_L("CCMRVideoRecorder::SetupEncoderL() out")));
       
   943             return;
       
   944             }
       
   945         }
       
   946 
       
   947     // Set source memory is allocated & released by camera API
       
   948     iDevVideoRec->SetSourceMemoryL( TReal(iSourceFrameRate), ETrue, KCMREncodingRealTime);
       
   949     // Set the source to memory buffers
       
   950     iDirectCapture = EFalse;
       
   951     PRINT((_L("CCMRVideoRecorder::SetupEncoderL() out")));
       
   952     }
       
   953 
       
   954 
       
   955 // ---------------------------------------------------------
       
   956 // CCMRVideoRecorder::ReadEncoderInfoL
       
   957 // Read encoder information object. The object is popped from
       
   958 // stack and MUST be handled properly by the caller
       
   959 // (other items were commented in a header).
       
   960 // ---------------------------------------------------------
       
   961 //
       
   962 CVideoEncoderInfo* CCMRVideoRecorder::ReadEncoderInfoL(TUid aUid)
       
   963     {
       
   964     PRINT((_L("CCMRVideoRecorder::ReadEncoderInfoL(), In")))
       
   965     CVideoEncoderInfo* info = iDevVideoRec->VideoEncoderInfoLC( aUid );
       
   966     CleanupStack::Pop(info);
       
   967 
       
   968     PRINT((_L("CCMRVideoRecorder::ReadEncoderInfoL(), Out")))
       
   969     return info;
       
   970     }
       
   971 
       
   972 
       
   973 // ---------------------------------------------------------
       
   974 // CCMRVideoRecorder::PrepareL
       
   975 // Prepares the recorder for recording
       
   976 // (other items were commented in a header).
       
   977 // ---------------------------------------------------------
       
   978 //
       
   979 void CCMRVideoRecorder::PrepareL()
       
   980     {
       
   981     PRINT((_L("CCMRVideoRecorder::PrepareL(), In")));
       
   982 
       
   983     if ( (State() != EStateOpen) && (State() != EStateReadyToRecord) )
       
   984         {
       
   985         PRINT((_L("CCMRVideoRecorder::PrepareL() wrong state")));
       
   986         User::Leave( KErrNotReady );
       
   987         }
       
   988 
       
   989 	if ( State() == EStateReadyToRecord )
       
   990 		{
       
   991 		// No prepare needed... already ready.
       
   992 		// everything ok, inform observer that we are prepared.
       
   993 		PRINT((_L("CCMRVideoRecorder::PrepareL(), Already prepared. Return right away")));
       
   994         DoSendEventToClient( KCMRPrepareComplete, KErrNone );
       
   995 		return;
       
   996 		}
       
   997 
       
   998 	if (iDevVideoRec)
       
   999 		{
       
  1000 		delete iDevVideoRec;
       
  1001 		iDevVideoRec = NULL;
       
  1002 		}
       
  1003 
       
  1004 	iDevVideoRec = CMMFDevVideoRecord::NewL( *this );
       
  1005 
       
  1006     // reset error code
       
  1007     iErrorCode = KErrNone;
       
  1008 
       
  1009     // If the user of the recorder API has not set valid settings,
       
  1010     // use default ones
       
  1011 
       
  1012     if ( ((iSizeIndex420 < 0) && (iSizeIndex422 < 0) && (iSizeIndexDCEncoder < 0))
       
  1013         || ((iSizeIndex420 >= iCameraInfo.iNumVideoFrameSizesSupported) && (iSizeIndex422 >= iCameraInfo.iNumVideoFrameSizesSupported)) )
       
  1014         {
       
  1015         // set default frame size
       
  1016         SetFrameSizeL( TSize( KCMRFrameWidth, KCMRFrameHeight ) );
       
  1017         }
       
  1018 
       
  1019     if ( ((iRateIndex420 < 0) && (iRateIndex422 < 0) && (iRateIndexDCEncoder < 0))
       
  1020         || ((iRateIndex420 >= iCameraInfo.iNumVideoFrameRatesSupported) && (iRateIndex422 >= iCameraInfo.iNumVideoFrameRatesSupported)) )
       
  1021         {
       
  1022         // set default frame rate
       
  1023         SetFrameRateL( KCMRFrameRate );
       
  1024         }
       
  1025 
       
  1026     // if during previous run a new frame rate was requested; when requested it affected only on encoding rate
       
  1027     if ( iRequestedFrameRate != iSourceFrameRate )
       
  1028         {
       
  1029         SetState(EStateOpen);//change state to make the SetFrameRate work correctly
       
  1030         SetFrameRateL( iRequestedFrameRate );
       
  1031         }
       
  1032 
       
  1033     // reset init completion flags
       
  1034     iEncoderInitComplete = EFalse;
       
  1035     iSourceInitComplete = EFalse;
       
  1036     iVideoCodecHWAccelerated = EFalse;
       
  1037     // Select & set parameters to video encoder
       
  1038     TRAPD(err, SetupEncoderL());
       
  1039     if ( err == KErrHardwareNotAvailable && iVideoCodecHWAccelerated )
       
  1040         {
       
  1041         // HW codec exists but can't be used, try again with ARM codec
       
  1042         SetupEncoderL();
       
  1043         }
       
  1044     else if ( err != KErrNone )
       
  1045         {
       
  1046         // some other error
       
  1047         PRINT((_L("CCMRVideoRecorder::PrepareL(), error [%d]"), err));
       
  1048         User::Leave( err );
       
  1049         }
       
  1050 
       
  1051     SetState(EStatePreparing);
       
  1052 
       
  1053     // Reserve camera for use
       
  1054     // Possibly asynchronous call (if not already reserved), completion is anyway informed using this->ReserveComplete()
       
  1055     // iSource has to be reserved only if we don't set hwdevice to use DirectCapture.
       
  1056     if ( !iDirectCapture )
       
  1057         {
       
  1058         iSource->Reserve();
       
  1059         }
       
  1060 
       
  1061     // Initialize DevVideoRec
       
  1062     // asynchronous call, completion informed using this->MdvroInitializeComplete()
       
  1063     iDevVideoRec->Initialize();
       
  1064 
       
  1065     PRINT((_L("CCMRVideoRecorder::PrepareL(), Out")));
       
  1066     }
       
  1067 
       
  1068 
       
  1069 // ---------------------------------------------------------
       
  1070 // CCMRVideoRecorder::RecordL
       
  1071 // Starts recording
       
  1072 // (other items were commented in a header).
       
  1073 // ---------------------------------------------------------
       
  1074 //
       
  1075 void CCMRVideoRecorder::RecordL()
       
  1076     {
       
  1077 	PRINT((_L("CCMRVideoRecorder::RecordL() - START - iRequestStatus: 0x%08x"), iRequestStatus ));
       
  1078 
       
  1079     if ( (State() == EStateRecording) || (State() == EStatePaused) )
       
  1080         {
       
  1081         // ignore, already recording
       
  1082         PRINT((_L("CCMRVideoRecorder::RecordL() ignore")));
       
  1083         return;
       
  1084         }
       
  1085 
       
  1086     if ( State() != EStateReadyToRecord )
       
  1087         {
       
  1088         PRINT((_L("CCMRVideoRecorder::RecordL() not ready")));
       
  1089         User::Leave(KErrNotReady);
       
  1090         }
       
  1091 
       
  1092     // check exposure setting from camera => decide framerates
       
  1093     CheckExposure();
       
  1094 
       
  1095 #ifdef _DEBUG
       
  1096     iRecordStartTime.UniversalTime();
       
  1097     iLastCapture.UniversalTime();
       
  1098 #endif
       
  1099     iNumberOfCapturedFrames = 0;
       
  1100     iNumberOfEncodedFrames = 0;
       
  1101     iEncoderInputQueueLength = 0;
       
  1102     iDriftFrameSkipCount = 0;
       
  1103     iAddedFrameDurationCount = 0;
       
  1104     iPreviousCameraFrameIndex = 0;
       
  1105     iDecSpecInfoLength = 0;
       
  1106 
       
  1107     // reset pause time adjustments variables
       
  1108     iTimeWhenPaused = 0;
       
  1109     iTotalPausedTime = 0;
       
  1110     iSystemClockDelta = 0;
       
  1111     iLatestUsedTimeStamp = -iSourceFrameInterval;
       
  1112     iLatestAbsoluteTimeStamp = 0;
       
  1113     iNumberOfCapturedFrames = 0;
       
  1114     iNumberOfVideoOutputBuffers = 0;
       
  1115 
       
  1116     if ( iVideoCodecData->DecoderConfigInfoUsed() )
       
  1117         {
       
  1118         // Read decoder specific information from the encoder
       
  1119         PRINT((_L("CCMRVideoRecorder::RecordL() asking CodingStandardSpecificInitOutputLC from the encoder.")));
       
  1120         iDecSpecInfo = iDevVideoRec->CodingStandardSpecificInitOutputLC();
       
  1121         if ( iDecSpecInfo )
       
  1122             {
       
  1123             PRINT((_L("CCMRVideoRecorder::RecordL() CodingStandardSpecificInitOutputLC received.")));
       
  1124             // it was placed to cleanupstack, pop it now since it takes some time before
       
  1125             // this ptr can be destructed, and if destructed from the stack, there may
       
  1126             // be newer objects in the stack at that time. The ptr is also now stored
       
  1127             // to member variable which must not be in stack
       
  1128             CleanupStack::Pop(iDecSpecInfo);
       
  1129 
       
  1130             // Inform the output that we have new data; it will read it in callback
       
  1131             if ( iRequestStatus )
       
  1132                 {
       
  1133 				PRINT((_L("CCMRVideoRecorder::RecordL() - completing output request..." )));
       
  1134                 iOutputThreadHandle.RequestComplete( iRequestStatus, KErrNone );
       
  1135                 }
       
  1136             }
       
  1137         else
       
  1138             {
       
  1139             // This codec should have decoder specific info field in metadata, hence leave with error
       
  1140             PRINT((_L("CCMRVideoRecorder::RecordL() no decoder specific info available from the encoder!?!")));
       
  1141             User::Leave( KErrNotSupported );
       
  1142             }
       
  1143         }
       
  1144 
       
  1145     // Start encoding
       
  1146     iDevVideoRec->Start();
       
  1147     iSkipBuffers = EFalse;
       
  1148 
       
  1149     iInputEnd = EFalse;
       
  1150     iStreamEnd = EFalse;
       
  1151 
       
  1152     // Start capturing
       
  1153     // StartCapture in case, if we don't use direct capture mode
       
  1154     if ( !iDirectCapture )
       
  1155         {
       
  1156         iSource->StartCapture();
       
  1157         }
       
  1158 
       
  1159     SetState(EStateRecording);
       
  1160 
       
  1161 	PRINT((_L("CCMRVideoRecorder::RecordL() - END - iRequestStatus: 0x%08x"), iRequestStatus ));
       
  1162     }
       
  1163 
       
  1164 
       
  1165 // ---------------------------------------------------------
       
  1166 // CCMRVideoRecorder::StopL
       
  1167 // Stops recording
       
  1168 // (other items were commented in a header).
       
  1169 // ---------------------------------------------------------
       
  1170 //
       
  1171 void CCMRVideoRecorder::StopL()
       
  1172     {
       
  1173     PRINT((_L("CCMRVideoRecorder::StopL(), In")))
       
  1174 
       
  1175     if ( (State() == EStateRecording) || (State() == EStatePaused) )
       
  1176         {
       
  1177         PRINT((_L("CCMRVideoRecorder::StopL(), Stop capture")));
       
  1178 
       
  1179         // Stop capturing
       
  1180         // Stop capture only incase, if we don't use direct capture mode
       
  1181         if ( !iDirectCapture )
       
  1182             {
       
  1183             iSource->StopCapture();
       
  1184             PRINT((_L("CCMRVideoRecorder::StopL() camera stopped")));
       
  1185             }
       
  1186 
       
  1187 
       
  1188         // Stopping is async => state can't be "recording"
       
  1189         SetState(EStateStopping);
       
  1190 
       
  1191         // Stop encoding
       
  1192         if ( !iFatalError )
       
  1193             {
       
  1194             iInputEnd = ETrue;
       
  1195             PRINT((_L("CCMRVideoRecorder::StopL(), calling DevVideo::InputEnd().")));                
       
  1196             iDevVideoRec->InputEnd();
       
  1197             // try to free buffers for video adaptation to complete video bitstream / EOS marker.
       
  1198             PRINT((_L("CCMRVideoRecorder::StopL(), flushing written frames back to DevVideo.")));                
       
  1199             iBufferReturnAO->Flush();
       
  1200             
       
  1201             // get all available buffers from devvideo
       
  1202             PRINT((_L("CCMRVideoRecorder::StopL(), getting all encoded frames from DevVideo.")));                
       
  1203             TVideoOutputBuffer* buffer = NULL;
       
  1204             for (;;)
       
  1205                 {
       
  1206                 TRAPD( err, ( buffer = iDevVideoRec->NextBufferL()));
       
  1207                 if ( err != KErrNone || buffer == NULL)
       
  1208                     {
       
  1209                     break;
       
  1210                     }
       
  1211                 // enter restricted area
       
  1212                 iMutexObj.Wait();
       
  1213                 // store
       
  1214                 TInt timestamp = I64INT(buffer->iCaptureTimestamp.Int64());
       
  1215                 PRINT((_L("CCMRVideoRecorder::StopL(), storing buffer: 0x%x, timestamp:%d"), buffer, timestamp ));                  
       
  1216                 iVideoOutputBufferInputQue.AddLast(*buffer);
       
  1217                 iNumberOfVideoOutputBuffers++;
       
  1218 
       
  1219                 // leave restricted area
       
  1220                 iMutexObj.Signal();
       
  1221                 }
       
  1222             }
       
  1223         else
       
  1224             {
       
  1225             PRINT((_L("CCMRVideoRecorder::StopL(), Fatal error was reported by devVideo, next step is to delete it")));
       
  1226 
       
  1227             // set state & inform MR => it can return from stop
       
  1228             SetState( EStateReadyToRecord );
       
  1229 
       
  1230             // everything ok, inform observer that we are ready for a new recording (iStopping does it too, though).
       
  1231             DoSendEventToClient( KCMRRecordingComplete, KErrNone );
       
  1232             }
       
  1233 
       
  1234         PRINT((_L("CCMRVideoRecorder::StopL() out, must wait for state change before stop completed")));
       
  1235         }
       
  1236     else
       
  1237         {
       
  1238         DoSendEventToClient( KCMRRecordingComplete, KErrNone );
       
  1239         PRINT((_L("CCMRVideoRecorder::StopL() out, already stopped")));
       
  1240         }
       
  1241     }
       
  1242 
       
  1243 // ---------------------------------------------------------
       
  1244 // CCMRVideoRecorder::RequestBuffersAndWaitEOSL
       
  1245 // While stopping keep requesting buffers from adaptation and waiting for EOS marker encodc signal
       
  1246 // (other items were commented in a header).
       
  1247 // ---------------------------------------------------------
       
  1248 //
       
  1249 
       
  1250 void CCMRVideoRecorder::RequestBuffersAndWaitEOSL(TInt& aVideoEOSReached)
       
  1251     {
       
  1252     PRINT((_L("CCMRVideoRecorder::RequestBuffersAndWaitEOSL(), in")))
       
  1253     PRINT((_L("CCMRVideoRecorder::RequestBuffersAndWaitEOSL(), flushing written frames back to DevVideo.")));                
       
  1254     iBufferReturnAO->Flush();
       
  1255 
       
  1256     // get all available buffers from devvideo
       
  1257     PRINT((_L("CCMRVideoRecorder::RequestBuffersAndWaitEOSL(), getting all encoded frames from DevVideo.")));                
       
  1258     TVideoOutputBuffer* buffer = NULL;
       
  1259     for (;;)
       
  1260         {
       
  1261         TRAPD( err, ( buffer = iDevVideoRec->NextBufferL()));
       
  1262         if ( err != KErrNone || buffer == NULL)
       
  1263             {
       
  1264             break;
       
  1265             }
       
  1266         // enter restricted area
       
  1267         iMutexObj.Wait();
       
  1268         // store
       
  1269         TInt timestamp = I64INT(buffer->iCaptureTimestamp.Int64());
       
  1270         PRINT((_L("CCMRVideoRecorder::RequestBuffersAndWaitEOSL(), storing buffer: 0x%x, timestamp:%d"), buffer, timestamp));                  
       
  1271         iVideoOutputBufferInputQue.AddLast(*buffer);
       
  1272         iNumberOfVideoOutputBuffers++;
       
  1273 
       
  1274         // leave restricted area
       
  1275         iMutexObj.Signal();
       
  1276         }
       
  1277     
       
  1278     aVideoEOSReached = iStreamEnd;
       
  1279     PRINT((_L("CCMRVideoRecorder::RequestBuffersAndWaitEOSL() out, aVideoEOSReached=%d"), aVideoEOSReached));
       
  1280     }
       
  1281 
       
  1282 // ---------------------------------------------------------
       
  1283 // CCMRVideoRecorder::PauseL
       
  1284 // Pauses recording
       
  1285 // (other items were commented in a header).
       
  1286 // ---------------------------------------------------------
       
  1287 //
       
  1288 void CCMRVideoRecorder::PauseL()
       
  1289     {
       
  1290     PRINT((_L("CCMRVideoRecorder::PauseL(), In")))
       
  1291 
       
  1292     if ( State() != EStateRecording )
       
  1293         {
       
  1294         return;
       
  1295         }
       
  1296 
       
  1297     SetState( EStatePaused );
       
  1298 
       
  1299     // Take the time stamp and later subtract it from real stamps
       
  1300     iTimeWhenPaused.UniversalTime();
       
  1301     PRINT((_L("CCMRVideoRecorder::PauseL() at %i:%i"),I64LOW(iTimeWhenPaused.Int64()), I64HIGH(iTimeWhenPaused.Int64()) ));
       
  1302 
       
  1303     // Adjust in the clock time changes, so we don't add it in twice during resume
       
  1304     iTimeWhenPaused = iTimeWhenPaused + iSystemClockDelta;
       
  1305     PRINT((_L("CCMRVideoRecorder::PauseL() at %i:%i"),I64LOW(iTimeWhenPaused.Int64()), I64HIGH(iTimeWhenPaused.Int64()) ));
       
  1306 
       
  1307     // Pause encoding
       
  1308     iDevVideoRec->Pause();
       
  1309     PRINT((_L("CCMRVideoRecorder::PauseL(), In")))
       
  1310     }
       
  1311 
       
  1312 
       
  1313 // ---------------------------------------------------------
       
  1314 // CCMRVideoRecorder::ResumeL
       
  1315 // Resumes recording
       
  1316 // (other items were commented in a header).
       
  1317 // ---------------------------------------------------------
       
  1318 //
       
  1319 void CCMRVideoRecorder::ResumeL()
       
  1320     {
       
  1321     PRINT((_L("CCMRVideoRecorder::ResumeL(), In")))
       
  1322 
       
  1323     if ( State() != EStatePaused )
       
  1324         {
       
  1325         return;
       
  1326         }
       
  1327 
       
  1328     // Resume encoding
       
  1329     iDevVideoRec->Resume();
       
  1330 
       
  1331     // measure the time we were paused; remember that this could have been Nth pause
       
  1332     TTime current;
       
  1333     current.UniversalTime();
       
  1334     iTotalPausedTime = iTotalPausedTime.Int64() + current.MicroSecondsFrom(iTimeWhenPaused-iSystemClockDelta).Int64();
       
  1335     PRINT((_L("CCMRVideoRecorder::ResumeL() at %i:%i, iTotalPausedTime now %d, iSystemClockDelta now %d"),I64LOW(current.Int64()),
       
  1336                                                                                                           I64HIGH(current.Int64()),
       
  1337                                                                                                           I64INT(iTotalPausedTime.Int64()),
       
  1338                                                                                                           I64INT(iSystemClockDelta.Int64()) ));
       
  1339 
       
  1340     SetState( EStateRecording );
       
  1341     PRINT((_L("CCMRVideoRecorder::ResumeL(), Out")))
       
  1342     }
       
  1343 
       
  1344 
       
  1345 // -----------------------------------------------------------------------------
       
  1346 // CCMRVideoRecorder::SetVideoCodecL
       
  1347 // Set video codec.
       
  1348 // (other items were commented in a header).
       
  1349 // -----------------------------------------------------------------------------
       
  1350 //
       
  1351 void CCMRVideoRecorder::SetVideoCodecL(const TDesC8& aMimeType)
       
  1352     {
       
  1353     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() in")));
       
  1354     if ( ( State() != EStateOpen ) && ( State() != EStateReadyToRecord ) )
       
  1355         {
       
  1356         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() wrong state")));
       
  1357         User::Leave(KErrNotReady);
       
  1358         }
       
  1359 
       
  1360     if ( iMimeType == aMimeType )
       
  1361         {
       
  1362         // the same codec was already selected, no need to change anything
       
  1363         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() out, no change needed. Requested codec already in use.")));
       
  1364         return;
       
  1365         }
       
  1366 
       
  1367 	TInt numerator = KCMRAspectRatioNum;
       
  1368 	TInt denominator = KCMRAspectRatioDenom;
       
  1369     TInt videoCodecLevel = 10;  // default: H.263 p0 level 10
       
  1370     TBuf8<256> newMimeType;
       
  1371     if ( aMimeType == KNullDesC8 )
       
  1372         {
       
  1373         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() Requested NULL video codec, default H.263 Baseline profile, level 10 in use.")));
       
  1374         // use default (H.263 p0 level 10); theoretically this could be useful if codec is first set to smth else and then reset to default
       
  1375         newMimeType = KCMRMimeTypeH263BaselineProfile;  //copy the contents
       
  1376         newMimeType += _L8( "; level=10" );    //append level
       
  1377         videoCodecLevel = 10;
       
  1378         }
       
  1379     else {
       
  1380         // check the given type first
       
  1381         TBuf8<256> string;
       
  1382         string = KCMRMimeTypeH263;
       
  1383         string += _L8( "*" );
       
  1384 
       
  1385         // the client-class checked the availability of the codec in the system already
       
  1386 
       
  1387         if ( aMimeType.MatchF( (const TDesC8& )string ) != KErrNotFound )
       
  1388             {
       
  1389             // H.263
       
  1390             PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263 requested")));
       
  1391             newMimeType = KCMRMimeTypeH263; //copy the contents
       
  1392 
       
  1393             if ( aMimeType.MatchF( _L8("*profile*") ) != KErrNotFound )
       
  1394                 {
       
  1395                 // profile given, check if we support it
       
  1396                 if ( aMimeType.MatchF( _L8("*profile=0*")) != KErrNotFound )
       
  1397                     {
       
  1398                     // profile 0 requested
       
  1399                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, profile 0 requested")));
       
  1400                     newMimeType += _L8( "; profile=0" );    //append
       
  1401                     }
       
  1402                 else if ( aMimeType.MatchF( _L8("*profile=3*")) != KErrNotFound )
       
  1403                     {
       
  1404                     // profile 3 requested
       
  1405                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, profile 3 requested")));
       
  1406                     newMimeType += _L8( "; profile=3" );    //append
       
  1407                     }
       
  1408                 else
       
  1409                     {
       
  1410                     // no other profiles supported
       
  1411                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() unsupported profile")));
       
  1412                     User::Leave(KErrNotSupported);
       
  1413                     }
       
  1414                 }
       
  1415             else
       
  1416                 {
       
  1417                 // no profile is given => assume 0
       
  1418                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, no profile requested - default to 0.")));
       
  1419                 newMimeType += _L8( "; profile=0" );    //append
       
  1420                 }
       
  1421 
       
  1422             if ( aMimeType.MatchF( _L8("*level=10*") ) != KErrNotFound )
       
  1423                 {
       
  1424                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 10 requested.")));
       
  1425                 videoCodecLevel = 10;
       
  1426                 newMimeType += _L8( "; level=10" );    //append
       
  1427                 }
       
  1428             else if ( aMimeType.MatchF( _L8("*level=20*") ) != KErrNotFound )
       
  1429                 {
       
  1430                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 20 requested.")));
       
  1431                 videoCodecLevel = 20;
       
  1432                 newMimeType += _L8( "; level=20" );    //append
       
  1433                 }
       
  1434             else if ( aMimeType.MatchF( _L8("*level=30*") ) != KErrNotFound )
       
  1435                 {
       
  1436                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 30 requested.")));
       
  1437                 videoCodecLevel = 30;
       
  1438                 newMimeType += _L8( "; level=30" );    //append
       
  1439                 }
       
  1440             else if ( aMimeType.MatchF( _L8("*level=40*") ) != KErrNotFound )
       
  1441                 {
       
  1442                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 40 requested.")));
       
  1443                 videoCodecLevel = 40;
       
  1444                 newMimeType += _L8( "; level=40" );    //append
       
  1445                 }
       
  1446             else if ( aMimeType.MatchF( _L8("*level=45*") ) != KErrNotFound )
       
  1447                 {
       
  1448                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 45 requested.")));
       
  1449                 videoCodecLevel = 45;
       
  1450                 newMimeType += _L8( "; level=45" );    //append
       
  1451                 }
       
  1452             else if ( aMimeType.MatchF( _L8("*level=50*") ) != KErrNotFound )
       
  1453                 {
       
  1454                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, level 50 requested.")));
       
  1455                 videoCodecLevel = 50;
       
  1456                 newMimeType += _L8( "; level=50" );    //append
       
  1457                 }
       
  1458             else if ( aMimeType.MatchF( _L8("*level*") ) != KErrNotFound )
       
  1459                 {
       
  1460                 // no other levels supported
       
  1461                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() unsupported level requested.")));
       
  1462                 User::Leave(KErrNotSupported);
       
  1463                 }
       
  1464             else
       
  1465                 {
       
  1466                 // if no level is given assume 10
       
  1467                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263, no level requested - default to 10.")));
       
  1468                 newMimeType += _L8( "; level=10" );    //append
       
  1469                 videoCodecLevel = 10;
       
  1470                 }
       
  1471 
       
  1472             // recreate the codec data object
       
  1473             PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.263 recreating codecdata.")));
       
  1474             delete iVideoCodecData;
       
  1475             iVideoCodecData = NULL;
       
  1476             iVideoCodecData = new (ELeave) CCMRVideoCodecDataH263(videoCodecLevel);
       
  1477             }
       
  1478         else
       
  1479             {
       
  1480 			numerator = KCMRMPEG4AspectRatioNum;
       
  1481 			denominator = KCMRMPEG4AspectRatioDenom;
       
  1482 
       
  1483             string = KCMRMimeTypeMPEG4V;
       
  1484             string += _L8( "*" );
       
  1485 
       
  1486             if ( aMimeType.MatchF( string ) != KErrNotFound )
       
  1487                 {
       
  1488                 // MPEG-4 Visual
       
  1489                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4 Visual requested")));
       
  1490                 newMimeType = KCMRMimeTypeMPEG4VSP; //copy the contents
       
  1491                 if ( aMimeType.MatchF( _L8("*profile-level-id=8*") ) != KErrNotFound )
       
  1492                     {
       
  1493                     // simple profile level 0
       
  1494                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 0 requested.")));
       
  1495                     videoCodecLevel = 0;
       
  1496                     newMimeType += _L8("8");
       
  1497                     }
       
  1498                 else if ( aMimeType.MatchF( _L8("*profile-level-id=9*") ) != KErrNotFound )
       
  1499                     {
       
  1500                     // simple profile level 0b
       
  1501                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 0b requested.")));
       
  1502                     videoCodecLevel = KCMRMPEG4SPLevel0B;
       
  1503                     newMimeType += _L8("9");
       
  1504                     }
       
  1505                 else if ( aMimeType.MatchF( _L8("*profile-level-id=1*") ) != KErrNotFound )
       
  1506                     {
       
  1507                     // simple profile level 1
       
  1508                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 1 requested.")));
       
  1509                     videoCodecLevel = 1;
       
  1510                     newMimeType += _L8("1");
       
  1511                     }
       
  1512                 else if ( aMimeType.MatchF( _L8("*profile-level-id=2*") ) != KErrNotFound )
       
  1513                     {
       
  1514                     // simple profile level 2
       
  1515                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 2 requested.")));
       
  1516                     videoCodecLevel = 2;
       
  1517                     newMimeType += _L8("2");
       
  1518                     }
       
  1519                 else if ( aMimeType.MatchF( _L8("*profile-level-id=3*") ) != KErrNotFound )
       
  1520                     {
       
  1521                     // simple profile level 3
       
  1522                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 3 requested.")));
       
  1523                     videoCodecLevel = 3;
       
  1524                     newMimeType += _L8("3");
       
  1525                     }
       
  1526                 else if ( aMimeType.MatchF( _L8("*profile-level-id=4*") ) != KErrNotFound )
       
  1527                     {
       
  1528                     // simple profile level 4
       
  1529                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 4a requested.")));
       
  1530                     videoCodecLevel = 4;
       
  1531                     newMimeType += _L8("4");
       
  1532                     }
       
  1533                 else if ( aMimeType.MatchF( _L8("*profile-level-id=5*") ) != KErrNotFound )
       
  1534                     {
       
  1535                     // simple profile level 5
       
  1536                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 5 requested.")));
       
  1537                     videoCodecLevel = 5;
       
  1538                     newMimeType += _L8("5");
       
  1539                     }
       
  1540                 else if ( aMimeType.MatchF( _L8("*profile-level-id=6*") ) != KErrNotFound )
       
  1541                     {
       
  1542                     // simple profile level 6
       
  1543                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, simple profile level 6 requested.")));
       
  1544                     videoCodecLevel = 6;
       
  1545                     newMimeType += _L8("6");
       
  1546                     }
       
  1547                 else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
       
  1548                     {
       
  1549                     // no other profile-level ids supported
       
  1550                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() unsupported profile-level requested.")));
       
  1551                     User::Leave(KErrNotSupported);
       
  1552                     }
       
  1553                 else
       
  1554                     {
       
  1555                     // Default is level 1
       
  1556                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4, no profile requested - defaulting to 1.")));
       
  1557                     videoCodecLevel = 1;
       
  1558                     newMimeType += _L8("1");
       
  1559                     }
       
  1560 
       
  1561                 // recreate the codec data object
       
  1562                 PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() MPEG-4 recreating codecdata.")));
       
  1563                 delete iVideoCodecData;
       
  1564                 iVideoCodecData = NULL;
       
  1565                 iVideoCodecData = new (ELeave) CCMRVideoCodecDataMPEG4(videoCodecLevel);
       
  1566                 }
       
  1567             else
       
  1568                 {
       
  1569 				numerator = KCMRMPEG4AspectRatioNum;
       
  1570 				denominator = KCMRMPEG4AspectRatioDenom;
       
  1571 
       
  1572                 string = KCMRMimeTypeH264AVC;
       
  1573                 string += _L8( "*" );
       
  1574 
       
  1575                 if ( aMimeType.MatchF( string ) != KErrNotFound )
       
  1576                     {
       
  1577                     // H.264/AVC
       
  1578                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC requested")));
       
  1579                     newMimeType = KCMRMimeTypeH264AVCProfileId; //copy the contents
       
  1580                     if ( aMimeType.MatchF( _L8("*profile-level-id=42800A*") ) != KErrNotFound )
       
  1581                         {
       
  1582                         // baseline profile level 1
       
  1583                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 1 requested.")));
       
  1584                         videoCodecLevel = KCMRH264AVCCodecLevel10;
       
  1585                         newMimeType += _L8("42800A");
       
  1586                         }
       
  1587                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound )
       
  1588                         {
       
  1589                         // baseline profile level 1b
       
  1590                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 1b requested.")));
       
  1591                         videoCodecLevel = KCMRH264AVCCodecLevel10b;
       
  1592                         newMimeType += _L8("42900B");
       
  1593                         }
       
  1594                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound )
       
  1595                         {
       
  1596                         // baseline profile level 1.1
       
  1597                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 1.1 requested.")));
       
  1598                         videoCodecLevel = KCMRH264AVCCodecLevel11;
       
  1599                         newMimeType += _L8("42800B");
       
  1600                         }
       
  1601                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42800C*") ) != KErrNotFound )
       
  1602                         {
       
  1603                         // baseline profile level 1.2
       
  1604                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 1.2 requested.")));
       
  1605                         videoCodecLevel = KCMRH264AVCCodecLevel12;
       
  1606                         newMimeType += _L8("42800C");
       
  1607                         }
       
  1608                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42800D*") ) != KErrNotFound )
       
  1609                         {
       
  1610                         // baseline profile level 1.3
       
  1611                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 1.3 requested.")));
       
  1612                         videoCodecLevel = KCMRH264AVCCodecLevel13;
       
  1613                         newMimeType += _L8("42800D");
       
  1614                         }
       
  1615                     else if ( aMimeType.MatchF( _L8("*profile-level-id=428014*") ) != KErrNotFound )
       
  1616                         {
       
  1617                         // baseline profile level 2
       
  1618                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 2 requested.")));
       
  1619                         videoCodecLevel = KCMRH264AVCCodecLevel20;
       
  1620                         newMimeType += _L8("428014");
       
  1621                         }
       
  1622                     else if ( aMimeType.MatchF( _L8("*profile-level-id=428015*") ) != KErrNotFound )
       
  1623                         {
       
  1624                         // baseline profile level 2.1
       
  1625                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 2.1 requested.")));
       
  1626                         videoCodecLevel = KCMRH264AVCCodecLevel21;
       
  1627                         newMimeType += _L8("428015");
       
  1628                         }
       
  1629                     else if ( aMimeType.MatchF( _L8("*profile-level-id=428016*") ) != KErrNotFound )
       
  1630                         {
       
  1631                         // baseline profile level 2.2
       
  1632                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 2.2 requested.")));
       
  1633                         videoCodecLevel = KCMRH264AVCCodecLevel22;
       
  1634                         newMimeType += _L8("428016");
       
  1635                         }
       
  1636                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42801E*") ) != KErrNotFound )
       
  1637                         {
       
  1638                         // baseline profile level 3
       
  1639                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 3 requested.")));
       
  1640                         videoCodecLevel = KCMRH264AVCCodecLevel30;
       
  1641                         newMimeType += _L8("42801E");
       
  1642                         }
       
  1643                     else if ( aMimeType.MatchF( _L8("*profile-level-id=42801F*") ) != KErrNotFound )
       
  1644                         {
       
  1645                         // baseline profile level 3.1
       
  1646                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 3.1 requested.")));
       
  1647                         videoCodecLevel = KCMRH264AVCCodecLevel31;
       
  1648                         newMimeType += _L8("42801F");
       
  1649                         }
       
  1650                     else if ( aMimeType.MatchF( _L8("*profile-level-id=428020*") ) != KErrNotFound )
       
  1651                         {
       
  1652                         // baseline profile level 3.2
       
  1653                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 3.2 requested.")));
       
  1654                         videoCodecLevel = KCMRH264AVCCodecLevel32;
       
  1655                         newMimeType += _L8("428020");
       
  1656                         }
       
  1657                     else if ( aMimeType.MatchF( _L8("*profile-level-id=428028*") ) != KErrNotFound )
       
  1658                         {
       
  1659                         // baseline profile level 4
       
  1660                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, baseline profile level 4 requested.")));
       
  1661                         videoCodecLevel = KCMRH264AVCCodecLevel40;
       
  1662                         newMimeType += _L8("428028");
       
  1663                         }
       
  1664                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D400A*") ) != KErrNotFound )
       
  1665                         {
       
  1666                         // main profile level 1
       
  1667                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 1 requested.")));
       
  1668                         videoCodecLevel = KCMRH264AVCCodecLevel10;
       
  1669                         newMimeType += _L8("4D400A");
       
  1670                         }
       
  1671                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D500B*") ) != KErrNotFound )
       
  1672                         {
       
  1673                         // main profile level 1b
       
  1674                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 1b requested.")));
       
  1675                         videoCodecLevel = KCMRH264AVCCodecLevel10b;
       
  1676                         newMimeType += _L8("4D500B");
       
  1677                         }
       
  1678                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D400B*") ) != KErrNotFound )
       
  1679                         {
       
  1680                         // main profile level 1.1
       
  1681                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 1.1 requested.")));
       
  1682                         videoCodecLevel = KCMRH264AVCCodecLevel11;
       
  1683                         newMimeType += _L8("4D400B");
       
  1684                         }
       
  1685                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D400C*") ) != KErrNotFound )
       
  1686                         {
       
  1687                         // main profile level 1.2
       
  1688                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 1.2 requested.")));
       
  1689                         videoCodecLevel = KCMRH264AVCCodecLevel12;
       
  1690                         newMimeType += _L8("4D400C");
       
  1691                         }
       
  1692                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D400D*") ) != KErrNotFound )
       
  1693                         {
       
  1694                         // main profile level 1.3
       
  1695                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 1.3 requested.")));
       
  1696                         videoCodecLevel = KCMRH264AVCCodecLevel13;
       
  1697                         newMimeType += _L8("4D400D");
       
  1698                         }
       
  1699                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D4014*") ) != KErrNotFound )
       
  1700                         {
       
  1701                         // main profile level 2
       
  1702                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 2 requested.")));
       
  1703                         videoCodecLevel = KCMRH264AVCCodecLevel20;
       
  1704                         newMimeType += _L8("4D4014");
       
  1705                         }
       
  1706                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D4015*") ) != KErrNotFound )
       
  1707                         {
       
  1708                         // main profile level 2.1
       
  1709                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 2.1 requested.")));
       
  1710                         videoCodecLevel = KCMRH264AVCCodecLevel21;
       
  1711                         newMimeType += _L8("4D4015");
       
  1712                         }
       
  1713                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D4016*") ) != KErrNotFound )
       
  1714                         {
       
  1715                         // main profile level 2.2
       
  1716                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 2.2 requested.")));
       
  1717                         videoCodecLevel = KCMRH264AVCCodecLevel22;
       
  1718                         newMimeType += _L8("4D4016");
       
  1719                         }
       
  1720                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D401E*") ) != KErrNotFound )
       
  1721                         {
       
  1722                         // main profile level 3
       
  1723                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 3 requested.")));
       
  1724                         videoCodecLevel = KCMRH264AVCCodecLevel30;
       
  1725                         newMimeType += _L8("4D401E");
       
  1726                         }
       
  1727                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D401F*") ) != KErrNotFound )
       
  1728                         {
       
  1729                         // main profile level 3.1
       
  1730                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 3.1 requested.")));
       
  1731                         videoCodecLevel = KCMRH264AVCCodecLevel31;
       
  1732                         newMimeType += _L8("4D401F");
       
  1733                         }
       
  1734                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D4020*") ) != KErrNotFound )
       
  1735                         {
       
  1736                         // main profile level 3.2
       
  1737                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 3.2 requested.")));
       
  1738                         videoCodecLevel = KCMRH264AVCCodecLevel32;
       
  1739                         newMimeType += _L8("4D4020");
       
  1740                         }
       
  1741                     else if ( aMimeType.MatchF( _L8("*profile-level-id=4D4028*") ) != KErrNotFound )
       
  1742                         {
       
  1743                         // main profile level 4
       
  1744                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, main profile level 4 requested.")));
       
  1745                         videoCodecLevel = KCMRH264AVCCodecLevel40;
       
  1746                         newMimeType += _L8("4D4028");
       
  1747                         }
       
  1748                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64400A*") ) != KErrNotFound )
       
  1749                         {
       
  1750                         // high profile level 1
       
  1751                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 1 requested.")));
       
  1752                         videoCodecLevel = KCMRH264AVCCodecLevel10;
       
  1753                         newMimeType += _L8("64400A");
       
  1754                         }
       
  1755                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644009*") ) != KErrNotFound )
       
  1756                         {
       
  1757                         // high profile level 1b
       
  1758                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 1b requested.")));
       
  1759                         videoCodecLevel = KCMRH264AVCCodecLevel10b;
       
  1760                         newMimeType += _L8("644009");
       
  1761                         }
       
  1762                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64400B*") ) != KErrNotFound )
       
  1763                         {
       
  1764                         // high profile level 1.1
       
  1765                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 1.1 requested.")));
       
  1766                         videoCodecLevel = KCMRH264AVCCodecLevel11;
       
  1767                         newMimeType += _L8("64400B");
       
  1768                         }
       
  1769                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64400C*") ) != KErrNotFound )
       
  1770                         {
       
  1771                         // high profile level 1.2
       
  1772                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 1.2 requested.")));
       
  1773                         videoCodecLevel = KCMRH264AVCCodecLevel12;
       
  1774                         newMimeType += _L8("64400C");
       
  1775                         }
       
  1776                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64400D*") ) != KErrNotFound )
       
  1777                         {
       
  1778                         // high profile level 1.3
       
  1779                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 1.3 requested.")));
       
  1780                         videoCodecLevel = KCMRH264AVCCodecLevel13;
       
  1781                         newMimeType += _L8("64400D");
       
  1782                         }
       
  1783                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644014*") ) != KErrNotFound )
       
  1784                         {
       
  1785                         // high profile level 2
       
  1786                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 2 requested.")));
       
  1787                         videoCodecLevel = KCMRH264AVCCodecLevel20;
       
  1788                         newMimeType += _L8("644014");
       
  1789                         }
       
  1790                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644015*") ) != KErrNotFound )
       
  1791                         {
       
  1792                         // high profile level 2.1
       
  1793                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 2.1 requested.")));
       
  1794                         videoCodecLevel = KCMRH264AVCCodecLevel21;
       
  1795                         newMimeType += _L8("644015");
       
  1796                         }
       
  1797                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644016*") ) != KErrNotFound )
       
  1798                         {
       
  1799                         // high profile level 2.2
       
  1800                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 2.2 requested.")));
       
  1801                         videoCodecLevel = KCMRH264AVCCodecLevel22;
       
  1802                         newMimeType += _L8("644016");
       
  1803                         }
       
  1804                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64401E*") ) != KErrNotFound )
       
  1805                         {
       
  1806                         // high profile level 3
       
  1807                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 3 requested.")));
       
  1808                         videoCodecLevel = KCMRH264AVCCodecLevel30;
       
  1809                         newMimeType += _L8("64401E");
       
  1810                         }
       
  1811                     else if ( aMimeType.MatchF( _L8("*profile-level-id=64401F*") ) != KErrNotFound )
       
  1812                         {
       
  1813                         // high profile level 3.1
       
  1814                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 3.1 requested.")));
       
  1815                         videoCodecLevel = KCMRH264AVCCodecLevel31;
       
  1816                         newMimeType += _L8("64401F");
       
  1817                         }
       
  1818                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644020*") ) != KErrNotFound )
       
  1819                         {
       
  1820                         // high profile level 3.2
       
  1821                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 3.2 requested.")));
       
  1822                         videoCodecLevel = KCMRH264AVCCodecLevel32;
       
  1823                         newMimeType += _L8("644020");
       
  1824                         }
       
  1825                     else if ( aMimeType.MatchF( _L8("*profile-level-id=644028*") ) != KErrNotFound )
       
  1826                         {
       
  1827                         // high profile level 4
       
  1828                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, high profile level 4 requested.")));
       
  1829                         videoCodecLevel = KCMRH264AVCCodecLevel40;
       
  1830                         newMimeType += _L8("644028");
       
  1831                         }
       
  1832                     else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
       
  1833                         {
       
  1834                         // no other profile-level ids supported
       
  1835                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() unsupported profile-level requested.")));
       
  1836                         User::Leave(KErrNotSupported);
       
  1837                         }
       
  1838                     else
       
  1839                         {
       
  1840                         // Default is level 1
       
  1841                         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC, no profile requested - defaulting to 1.")));
       
  1842                         videoCodecLevel = KCMRH264AVCCodecLevel10;
       
  1843                         newMimeType += _L8("42800A");
       
  1844                         }
       
  1845 
       
  1846                     // recreate the codec data object
       
  1847                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() H.264/AVC recreating codecdata.")));
       
  1848                     delete iVideoCodecData;
       
  1849                     iVideoCodecData = NULL;
       
  1850                     iVideoCodecData = new (ELeave) CCMRVideoCodecDataH264AVC(videoCodecLevel);
       
  1851                     }
       
  1852                 else
       
  1853                     {
       
  1854                     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() Unknown mimetype requested.")));
       
  1855                     // unknown mimetype
       
  1856                     }
       
  1857                 }
       
  1858             }
       
  1859         }
       
  1860 
       
  1861     // successfully interpreted the input mime type
       
  1862     if ( newMimeType != iMimeType )
       
  1863 	    {
       
  1864         iMimeType = newMimeType; //copy the contents
       
  1865 		PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() new supported video codec requested - updating available encoders.")));
       
  1866 		iAvailableVideoEncoders.Reset();
       
  1867         if ( iPreferredEncoderUID != KNullUid )
       
  1868             {// We have preferred encoder UID from client - override encoder search and use it instead.
       
  1869             PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() skipping encoder search. Using API user encoder: %d "), iPreferredEncoderUID.iUid));
       
  1870             iAvailableVideoEncoders.AppendL(iPreferredEncoderUID);
       
  1871             }
       
  1872         else if ( iConfig &&
       
  1873                 ( iConfig->IsICMConfigDataAvailable() ) &&
       
  1874                 ( iConfig->VideoQualitySettings().iVideoEncoderUID != KNullUid ) )
       
  1875             {// Video quality set has set UID value - override encoder search and use it instead.
       
  1876             PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() skipping encoder search. Using ICM config encoder: %d "), iPreferredEncoderUID.iUid));
       
  1877             iAvailableVideoEncoders.AppendL(iPreferredEncoderUID);
       
  1878             }
       
  1879         else
       
  1880             {
       
  1881             iDevVideoRec->FindEncodersL(iMimeType, 0 /* aPreProc */, iAvailableVideoEncoders, EFalse );
       
  1882             PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() search found %d encoder(s)"), iAvailableVideoEncoders.Count() ));
       
  1883             }
       
  1884         iConfig->SetVideoCodec(iMimeType);
       
  1885         iConfig->SetVideoPixelAspectRatio(numerator, denominator);
       
  1886 
       
  1887         UpdateSupportedVideoFrameSizesRates();
       
  1888 
       
  1889         // user has to call this->PrepareL() now that a setting has been changed !!!
       
  1890         // allow to start recording only when the state is "EReadyToRecord"
       
  1891         PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() codec set, prepare needed before recording.")));
       
  1892         SetState(EStateOpen);
       
  1893         DoSendEventToClient( KCMRPrepareNeeded, iErrorCode );   // use iErrorCode in case we had stored error; it may be KErrNone too
       
  1894         iErrorCode = KErrNone;
       
  1895 	    }
       
  1896 
       
  1897     PRINT((_L("CCMRVideoRecorder::SetVideoCodecL() out")));
       
  1898     }
       
  1899 
       
  1900 // -----------------------------------------------------------------------------
       
  1901 // CCMRVideoRecorder::GetVideoCodec
       
  1902 // Get the used video codec.
       
  1903 // (other items were commented in a header).
       
  1904 // -----------------------------------------------------------------------------
       
  1905 //
       
  1906 void CCMRVideoRecorder::GetVideoCodecL( TDes8& aVideoMimeType ) const
       
  1907     {
       
  1908     aVideoMimeType = iMimeType;
       
  1909     }
       
  1910 
       
  1911 
       
  1912 // ---------------------------------------------------------
       
  1913 // CCMRVideoRecorder::SetTargetBitRateL
       
  1914 // Sets new target bitrate
       
  1915 // (other items were commented in a header).
       
  1916 // ---------------------------------------------------------
       
  1917 //
       
  1918 void CCMRVideoRecorder::SetTargetBitRateL(TInt aBitRate)
       
  1919     {
       
  1920     PRINT((_L("CCMRVideoRecorder::SetTargetBitRate, aBitrate = % d"),aBitRate));
       
  1921 
       
  1922     if ( aBitRate == KMMFVariableVideoBitRate )
       
  1923         {
       
  1924         // Variable rate requested; normalize the bit-rate (temporarily only in this function)
       
  1925         // but set a mode
       
  1926         aBitRate = iVideoCodecData->MaxBitRate();
       
  1927         iBitRateMode = EBitRateVariable;
       
  1928         }
       
  1929     else
       
  1930         {
       
  1931         iBitRateMode = EBitRateConstant;
       
  1932         }
       
  1933 
       
  1934     // check that values are reasonable; check max bitrate only when the level is expected to be used for MMS
       
  1935     if ( (aBitRate < KCMRMinAcceptedBitRate) || ((iVideoCodecData->LevelForMMS()) && (aBitRate > iVideoCodecData->MaxBitRate())) )
       
  1936         {
       
  1937         PRINT((_L("CCMRVideoRecorder::SetTargetBitRateL() illegal bitrate")));
       
  1938         User::Leave(KErrArgument);
       
  1939         }
       
  1940 
       
  1941     // call base class implementation
       
  1942     CCMRRecorderBase::SetTargetBitRateL(aBitRate);
       
  1943 
       
  1944     // inform the max bitrate to the sink
       
  1945     User::LeaveIfError( iOutput->SetMaxVideoBitRate( aBitRate ) );
       
  1946 
       
  1947     //inform the estimated average bitrate to sink; use a HW-specific scaler to estimate the average
       
  1948     TReal videoBitrateScaler = 0;
       
  1949     if ( iConfig )
       
  1950     	{
       
  1951         videoBitrateScaler = iConfig->PluginSettings().iCMRAvgVideoBitRateScaler;
       
  1952     	}
       
  1953 
       
  1954     // make sure we never get scaler value 0 (ends up Div0 error)
       
  1955     if ( videoBitrateScaler == 0 )
       
  1956     	{
       
  1957     	videoBitrateScaler = KCMRAvgVideoBitRateScaler;
       
  1958     	}
       
  1959 
       
  1960     TInt br = static_cast<TInt>(aBitRate*videoBitrateScaler);
       
  1961     User::LeaveIfError( iOutput->SetAverageVideoBitRate( br ) );
       
  1962 
       
  1963     if ( StateRequiresDynamicSetting() )
       
  1964         {
       
  1965         // we have prepared => new value must be given via dynamic methods
       
  1966         FillRateControlOptions( iRateControlOptions );
       
  1967         iDevVideoRec->SetRateControlOptions(0, iRateControlOptions); // only base layer (layer 0) supported
       
  1968         }
       
  1969     else
       
  1970         {
       
  1971         // we are not recording or prepared => value will be given forward in prepare
       
  1972         }
       
  1973     }
       
  1974 
       
  1975 
       
  1976 // ---------------------------------------------------------
       
  1977 // CCMRVideoRecorder::TargetBitRateL
       
  1978 // Gets current target bitrate
       
  1979 // (other items were commented in a header).
       
  1980 // ---------------------------------------------------------
       
  1981 //
       
  1982 void CCMRVideoRecorder::TargetBitRateL(TInt& aBitRate)
       
  1983     {
       
  1984     PRINT((_L("CCMRVideoRecorder::TargetBitRate")));
       
  1985 
       
  1986 
       
  1987     if ( iBitRateMode == EBitRateConstant )
       
  1988         {
       
  1989         aBitRate = iTargetBitRate;
       
  1990         }
       
  1991     else
       
  1992         {
       
  1993         aBitRate = KMMFVariableVideoBitRate;
       
  1994         }
       
  1995     }
       
  1996 
       
  1997 
       
  1998 // ---------------------------------------------------------
       
  1999 // CCMRVideoRecorder::SetFrameSizeL
       
  2000 // Sets new input & output frame size
       
  2001 // (other items were commented in a header).
       
  2002 // ---------------------------------------------------------
       
  2003 //
       
  2004 void CCMRVideoRecorder::SetFrameSizeL(const TSize& aSize)
       
  2005     {
       
  2006 
       
  2007     PRINT((_L("CCMRVideoRecorder::SetFrameSizeL(), In, size: %dx%d"), aSize.iWidth, aSize.iHeight ));
       
  2008 
       
  2009     // allow settings only when in "open" or "readytorecord" states
       
  2010     if ( ( State() != EStateOpen ) && ( State() != EStateReadyToRecord ) )
       
  2011         {
       
  2012         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() wrong state")));
       
  2013         User::Leave(KErrNotReady);
       
  2014         }
       
  2015 
       
  2016     // check that size is acceptable
       
  2017     if ( !iVideoCodecData->MaxFrameSize( aSize ) )
       
  2018         {
       
  2019         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() illegal frame size")));
       
  2020         User::Leave(KErrArgument);//could be also KErrNotSupported
       
  2021         }
       
  2022 
       
  2023     TSize size;
       
  2024     TInt i = 0;
       
  2025     TInt j = 0;
       
  2026    	TInt k = 0;
       
  2027 
       
  2028     PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() looking match for frame size: %d x %d from camera"), aSize.iWidth, aSize.iHeight ));
       
  2029 
       
  2030     // Some explanation of the logic here. Camera API must support the same rates for all formats, since there
       
  2031     // is just a single variable in the info class to check the number of rates.
       
  2032     // But the indices may differ and that's why we need enumerations
       
  2033     if ( iCameraInfo.iVideoFrameFormatsSupported & CCamera::EFormatYUV420Planar )
       
  2034         {
       
  2035         // check YUV420 planar
       
  2036         for ( i = 0; i < iCameraInfo.iNumVideoFrameSizesSupported; i++ )
       
  2037             {
       
  2038             iSource->EnumerateVideoFrameSizes(size, i, CCamera::EFormatYUV420Planar);
       
  2039             PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera EFormatYUV420Planar %d x %d found from camera"), size.iWidth, size.iHeight ));
       
  2040 
       
  2041             if ( size == aSize )
       
  2042                 {
       
  2043                 PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera EFormatYUV420Planar %d x %d Matched."), size.iWidth, size.iHeight ));
       
  2044                 iSizeIndex420 = i;
       
  2045                 break;
       
  2046                 }
       
  2047             }
       
  2048         }
       
  2049     else
       
  2050         {
       
  2051         i = iCameraInfo.iNumVideoFrameSizesSupported;
       
  2052         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera doesn't support EFormatYUV420Planar")));
       
  2053         }
       
  2054 
       
  2055     if ( iCameraInfo.iVideoFrameFormatsSupported & CCamera::EFormatYUV422 )
       
  2056         {
       
  2057         // check YUV422 interleaved
       
  2058         for ( j = 0; j < iCameraInfo.iNumVideoFrameSizesSupported; j++ )
       
  2059             {
       
  2060             iSource->EnumerateVideoFrameSizes(size, j, CCamera::EFormatYUV422 );
       
  2061             PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera EFormatYUV422 %d x %d found from camera"), size.iWidth, size.iHeight ));
       
  2062 
       
  2063             if ( size == aSize )
       
  2064                 {
       
  2065                 PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera EFormatYUV422 %d x %d Matched."), size.iWidth, size.iHeight ));
       
  2066                 iSizeIndex422 = j;
       
  2067                 break;
       
  2068                 }
       
  2069             }
       
  2070         }
       
  2071     else
       
  2072         {
       
  2073         j = iCameraInfo.iNumVideoFrameSizesSupported;
       
  2074         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() Camera doesn't support EFormatYUV422")));
       
  2075         }
       
  2076 
       
  2077 	// Search if we have direct capture encoder available -> no need to care about camera supported sizes.
       
  2078 	if ( iAvailableVideoFrameSizesRates.Count() )
       
  2079 		{
       
  2080         // check direct capture encoder size array
       
  2081         for ( k = 0; k < iAvailableVideoFrameSizesRates.Count(); k++ )
       
  2082             {
       
  2083             // All target resolutions that are below higher resolution found from encoders are accepted.
       
  2084             if ( (iAvailableVideoFrameSizesRates[k].iPictureSize.iWidth >= aSize.iWidth) &&
       
  2085             	 (iAvailableVideoFrameSizesRates[k].iPictureSize.iHeight >= aSize.iHeight) )
       
  2086                 {
       
  2087                 PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() DirectCapture encoder %d x %d Matched."), aSize.iWidth, aSize.iHeight ));
       
  2088 				iSizeIndexDCEncoder = k;
       
  2089                 break;
       
  2090                 }
       
  2091             }
       
  2092 		}
       
  2093 	else
       
  2094 		{
       
  2095 		PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() no directcapture encoder available for given size.")));
       
  2096 		}
       
  2097 
       
  2098     if ( (i == iCameraInfo.iNumVideoFrameSizesSupported) &&
       
  2099     	 (j == iCameraInfo.iNumVideoFrameSizesSupported) &&
       
  2100     	 (k == iAvailableVideoFrameSizesRates.Count()) )
       
  2101         {
       
  2102         // Requested size not supported by camera API or the directcapture encoder
       
  2103         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL(), Camera and/or direct capture encoder does not support this resolution")));
       
  2104         User::Leave(KErrNotSupported);
       
  2105         }
       
  2106 
       
  2107     iFrameSize = aSize;
       
  2108     iOutput->SetVideoFrameSize(aSize);
       
  2109 
       
  2110     // user has to call this->PrepareL() now that a setting has been changed !!!
       
  2111     // allow to start recording only when the state is "EReadyToRecord"
       
  2112     SetState(EStateOpen);
       
  2113     DoSendEventToClient( KCMRPrepareNeeded, iErrorCode );   // use iErrorCode in case we had stored error; it may be KErrNone too
       
  2114     iErrorCode = KErrNone;
       
  2115 
       
  2116     // update MaxFrameRate to new frame size
       
  2117     iMaxFrameRate4GivenSize = iVideoCodecData->MaxFrameRate( iFrameSize );
       
  2118 
       
  2119     // framerate is tied with framesize; if it was set before update it accordingly
       
  2120     // this may be overridden by user e.g. with a higher rate; this sets the rates <= previous encoding rate
       
  2121     if ( (iRateIndex420 >= 0) || (iRateIndex422 >= 0) || (iRateIndexDCEncoder >= 0) )
       
  2122         {
       
  2123         // must use iEncodingFrameRate, since other rates may raise encoding rate higher than wanted; this allows camera frame rate to be higher
       
  2124         TInt success = KErrNone;
       
  2125         do
       
  2126             {
       
  2127             TRAP( success, SetFrameRateL( iEncodingFrameRate ));
       
  2128             if ( success == KErrNone )
       
  2129                 {
       
  2130                 break;
       
  2131                 }
       
  2132             // if picture size was increased, we may need to decrease framerate
       
  2133             iEncodingFrameRate--;
       
  2134             } while ( iEncodingFrameRate > 0 );
       
  2135             if ( success != KErrNone )
       
  2136                 {
       
  2137                 // This framesize - framerate combination not possible
       
  2138                 PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() illegal frame size - rate combination")));
       
  2139                 User::Leave(success);
       
  2140                 }
       
  2141         }
       
  2142 
       
  2143     PRINT((_L("CCMRVideoRecorder::SetFrameSizeL(), Out")));
       
  2144     }
       
  2145 
       
  2146 
       
  2147 // ---------------------------------------------------------
       
  2148 // CCMRVideoRecorder::FrameSizeL
       
  2149 // Gets current frame size
       
  2150 // (other items were commented in a header).
       
  2151 // ---------------------------------------------------------
       
  2152 //
       
  2153 void CCMRVideoRecorder::FrameSizeL(TSize& aSize) const
       
  2154     {
       
  2155     PRINT((_L("CCMRVideoRecorder::FrameSizeL()")));
       
  2156     aSize = iFrameSize;
       
  2157     }
       
  2158 
       
  2159 
       
  2160 // ---------------------------------------------------------
       
  2161 // CCMRVideoRecorder::SetFrameRateL
       
  2162 // Sets new target frame rate
       
  2163 // (other items were commented in a header).
       
  2164 // ---------------------------------------------------------
       
  2165 //
       
  2166 void CCMRVideoRecorder::SetFrameRateL(TReal32 aFrameRate)
       
  2167     {
       
  2168     PRINT((_L("CCMRVideoRecorder::SetFrameRate(), requested rate %f"), aFrameRate));
       
  2169 
       
  2170     // Size has to be set before setting frame rate !!!
       
  2171     if ( (State() == EStateNone) || ((iSizeIndex420 < 0) && (iSizeIndex422 < 0) && (iSizeIndexDCEncoder < 0)) )
       
  2172         {
       
  2173         PRINT((_L("CCMRVideoRecorder::SetFrameRateL() wrong state")));
       
  2174         User::Leave(KErrNotReady);
       
  2175         }
       
  2176 
       
  2177     // check that values are reasonable
       
  2178     if ( (aFrameRate <= 0) || (aFrameRate > iVideoCodecData->MaxFrameRate(iFrameSize)) )
       
  2179         {
       
  2180         PRINT((_L("CCMRVideoRecorder::SetFrameSizeL() illegal frame rate")));
       
  2181         User::Leave(KErrArgument);
       
  2182         }
       
  2183 
       
  2184     // encoding frame rate is always the requested one
       
  2185     if ( aFrameRate <= iMaxFrameRate4GivenSize ) // actually iMaxFrameRate4GivenSize is valid only after prepare
       
  2186         {
       
  2187         // requested rate looks ok
       
  2188         iEncodingFrameRate = aFrameRate;
       
  2189         }
       
  2190     else if ( iEncodingFrameRate < iMaxFrameRate4GivenSize )
       
  2191         {
       
  2192         // too high rate requested, but the current rate is still lower than max possible, so we can set the rate higher anyway
       
  2193         iEncodingFrameRate = static_cast<TReal32>(iMaxFrameRate4GivenSize);
       
  2194         PRINT((_L("CCMRVideoRecorder::SetFrameRate(), requested rate is too high for the used encoder, but set it to this rate: %f"), iMaxFrameRate4GivenSize));
       
  2195         }
       
  2196     else
       
  2197         {
       
  2198         // The change has no effect; the used encoder is already set to max possible rate and can't be configured for the requested rate
       
  2199         // for now camera api capability is not checked; e.g. if H.263 level is 20 => framerate could be 30fps for QCIF but if max encoder
       
  2200         // impl. rate is 10fps, we don't leave, but just ignore
       
  2201         PRINT((_L("CCMRVideoRecorder::SetFrameRate(), requested rate is too high for the used encoder, max rate %f"), iMaxFrameRate4GivenSize));
       
  2202         return;
       
  2203         }
       
  2204 
       
  2205     if ( StateRequiresDynamicSetting() )
       
  2206         {
       
  2207         // we are running, change only encoding rate now
       
  2208 
       
  2209         // store the requested rate also, to be taken into use in the next prepare
       
  2210         if ( !iNightMode )
       
  2211             {
       
  2212             iRequestedFrameRate = aFrameRate;
       
  2213             }
       
  2214 
       
  2215         if ( iEncodingFrameRate > iSourceFrameRate )
       
  2216             {
       
  2217             // can't be higher than capture rate, limit it
       
  2218             iEncodingFrameRate = iSourceFrameRate;
       
  2219             }
       
  2220 
       
  2221         // set the rate control params
       
  2222         FillRateControlOptions( iRateControlOptions );
       
  2223         iDevVideoRec->SetRateControlOptions(0, iRateControlOptions); // only base layer (layer 0) supported
       
  2224         }
       
  2225     else
       
  2226         {
       
  2227         // we are in initialization phase, change also camera rate
       
  2228 
       
  2229         TReal32 rate;
       
  2230         TInt i;
       
  2231 
       
  2232         iRateIndex420 = -1; //reset just in case, needed to determine if the loop below was successful
       
  2233         iRateIndex422 = -1; //reset just in case, needed to determine if the loop below was successful
       
  2234         iRateIndexDCEncoder = -1;
       
  2235 
       
  2236         // Some explanation of the logic here. Camera API must support the same rates for all formats, since there
       
  2237         // is just a single variable in the info class to check the number of rates.
       
  2238         // But the indices may differ and that's why we need enumerations
       
  2239         // Since we prefer YUV422, it can override the member variables.
       
  2240 
       
  2241         if ( iCameraInfo.iVideoFrameFormatsSupported & CCamera::EFormatYUV420Planar )
       
  2242             {
       
  2243             // check YUV420 planar
       
  2244 
       
  2245             // search for an exact match from camera's supported rates
       
  2246             for ( i = 0; i < iCameraInfo.iNumVideoFrameRatesSupported; i++ )
       
  2247                 {
       
  2248 
       
  2249                 iSource->EnumerateVideoFrameRates(rate, i, CCamera::EFormatYUV420Planar, iSizeIndex420,
       
  2250                                                   CCamera::EExposureAuto);
       
  2251 
       
  2252                 if ( rate == aFrameRate )
       
  2253                     {
       
  2254                     iRateIndex420 = i;
       
  2255                     iSourceFrameRate = aFrameRate;
       
  2256                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2257                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, asked framerate found")));
       
  2258                     break;
       
  2259                     }
       
  2260                 else if ( rate > aFrameRate )
       
  2261                     {
       
  2262                     // this is higher but could be used (encoder can match the rates)
       
  2263                     // Check the other rates too if a better is found
       
  2264                     iRateIndex420 = i;
       
  2265                     iSourceFrameRate = rate;
       
  2266                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2267                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, a higher source framerate found")));
       
  2268                     }
       
  2269                 }
       
  2270             }
       
  2271 
       
  2272         if ( iCameraInfo.iVideoFrameFormatsSupported & CCamera::EFormatYUV422 )
       
  2273             {
       
  2274             // check YUV422 interleaved
       
  2275 
       
  2276             // search for an exact match from camera's supported rates
       
  2277             for ( i = 0; i < iCameraInfo.iNumVideoFrameRatesSupported; i++ )
       
  2278                 {
       
  2279                 iSource->EnumerateVideoFrameRates(rate, i, CCamera::EFormatYUV422, iSizeIndex422,
       
  2280                                                   CCamera::EExposureAuto);
       
  2281 
       
  2282                 if ( rate == aFrameRate )
       
  2283                     {
       
  2284                     iRateIndex422 = i;
       
  2285                     iSourceFrameRate = aFrameRate;
       
  2286                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2287                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, asked framerate found")));
       
  2288                     break;
       
  2289                     }
       
  2290                 else if ( rate > aFrameRate )
       
  2291                     {
       
  2292                     // this is higher but could be used (encoder can match the rates)
       
  2293                     // Check the other rates too if a better is found
       
  2294                     iRateIndex422 = i;
       
  2295                     iSourceFrameRate = rate;
       
  2296                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2297                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, a higher source framerate found")));
       
  2298                     }
       
  2299                 }
       
  2300             }
       
  2301 
       
  2302         if ( iAvailableVideoFrameSizesRates.Count() && (iSizeIndexDCEncoder >= 0) && (iSizeIndexDCEncoder < iAvailableVideoFrameSizesRates.Count()) )
       
  2303             {
       
  2304             // check Direct capture encoder supported rates.
       
  2305 
       
  2306             // search for an exact match from encoders supported rates
       
  2307             for ( i = 0; i < iAvailableVideoFrameSizesRates.Count(); i++ )
       
  2308                 {
       
  2309                 if ( (iAvailableVideoFrameSizesRates[i].iPictureRate == aFrameRate) &&
       
  2310                 	 (iAvailableVideoFrameSizesRates[i].iPictureSize == iAvailableVideoFrameSizesRates[iSizeIndexDCEncoder].iPictureSize) )
       
  2311                     {
       
  2312                     iRateIndexDCEncoder = i;
       
  2313                     iSizeIndexDCEncoder = i;
       
  2314                     iSourceFrameRate = aFrameRate;
       
  2315                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2316                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, asked framerate found")));
       
  2317                     break;
       
  2318                     }
       
  2319                 else if ( (iAvailableVideoFrameSizesRates[i].iPictureRate >= aFrameRate) &&
       
  2320                 	 	  (iAvailableVideoFrameSizesRates[i].iPictureSize.iWidth >= iAvailableVideoFrameSizesRates[iSizeIndexDCEncoder].iPictureSize.iWidth ) &&
       
  2321                 	 	  (iAvailableVideoFrameSizesRates[i].iPictureSize.iHeight >= iAvailableVideoFrameSizesRates[iSizeIndexDCEncoder].iPictureSize.iHeight ) )
       
  2322                     {
       
  2323                     // this is higher but could be used (encoder can match the rates)
       
  2324                     // Check the other rates too if a better is found
       
  2325                     iRateIndexDCEncoder = i;
       
  2326                     iSizeIndexDCEncoder = i;
       
  2327                     iSourceFrameRate = aFrameRate;
       
  2328                     iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  2329                     PRINT((_L("CCMRVideoRecorder::SetFrameRate, a higher source framerate found: %dx%d at %f"), iAvailableVideoFrameSizesRates[i].iPictureSize.iWidth,
       
  2330                     																							iAvailableVideoFrameSizesRates[i].iPictureSize.iHeight,
       
  2331                     																							iAvailableVideoFrameSizesRates[i].iPictureRate ));
       
  2332                     }
       
  2333                 }
       
  2334             }
       
  2335 
       
  2336 
       
  2337         if ( (iRateIndex420 < 0) && (iRateIndex422 < 0) && (iRateIndexDCEncoder < 0) )
       
  2338             {
       
  2339             // there is no suitable frame rate available, not even a higher one, return error
       
  2340             PRINT((_L("CCMRVideoRecorder::SetFrameRate, no suitable framerate found from Camera API and/or direct capture encoder.")));
       
  2341             User::Leave(KErrNotSupported);
       
  2342             }
       
  2343 
       
  2344         // set to the actual rate to prevent trying set the rate again from PrepareL
       
  2345         iRequestedFrameRate = iSourceFrameRate;
       
  2346 
       
  2347         // user has to call this->PrepareL() now that a setting has been changed !!!
       
  2348         // allow to start recording only when the state is "EReadyToRecord"
       
  2349         if ( State() != EStateOpen )
       
  2350             {
       
  2351             SetState(EStateOpen);
       
  2352             DoSendEventToClient( KCMRPrepareNeeded, iErrorCode );   // use iErrorCode in case we had stored error; it may be KErrNone too
       
  2353             iErrorCode = KErrNone;
       
  2354             }
       
  2355         }
       
  2356     }
       
  2357 
       
  2358 
       
  2359 // ---------------------------------------------------------
       
  2360 // CCMRVideoRecorder::FrameRateL
       
  2361 // Get the used encoding frame rate
       
  2362 // (other items were commented in a header).
       
  2363 // ---------------------------------------------------------
       
  2364 //
       
  2365 void CCMRVideoRecorder::FrameRateL(TReal32& aFrameRate) const
       
  2366     {
       
  2367     PRINT((_L("CCMRVideoRecorder::FrameRateL()")));
       
  2368     aFrameRate = iEncodingFrameRate;
       
  2369     }
       
  2370 
       
  2371 
       
  2372 // ---------------------------------------------------------
       
  2373 // CCMRVideoRecorder::SetVideoCodingOptionsL
       
  2374 // Set misc video coding options
       
  2375 // (other items were commented in a header).
       
  2376 // ---------------------------------------------------------
       
  2377 //
       
  2378 void CCMRVideoRecorder::SetVideoCodingOptionsL(const TCCMRVideoCodingOptions& aOptions)
       
  2379     {
       
  2380     if ( ( State() != EStateOpen ) && ( State() != EStateReadyToRecord ) )
       
  2381         {
       
  2382         PRINT((_L("CCMRVideoRecorder::SetVideoCodingOptionsL() wrong state")));
       
  2383         User::Leave( KErrNotReady );
       
  2384         }
       
  2385     if ( iMinRandomAccessPeriodInSeconds != KCMRUseDefault )
       
  2386         {
       
  2387         iMinRandomAccessPeriodInSeconds = aOptions.iMinRandomAccessPeriodInSeconds;
       
  2388         }
       
  2389 
       
  2390     iVideoCodecData->SetVideoCodingOptionsL(aOptions);
       
  2391     }
       
  2392 
       
  2393 
       
  2394 // ---------------------------------------------------------
       
  2395 // CCMRVideoRecorder::SetVideoRateControlOptionsL
       
  2396 // Set video rate control options
       
  2397 // (other items were commented in a header).
       
  2398 // ---------------------------------------------------------
       
  2399 //
       
  2400 void CCMRVideoRecorder::SetVideoRateControlOptionsL(const TRateControlOptions& aOptions)
       
  2401     {
       
  2402     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() in")));
       
  2403     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() TBitrateControlType iControl: %d"), aOptions.iControl));
       
  2404     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() iBitrate: %d"), aOptions.iBitrate));
       
  2405     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() iPictureQuality: %d"), aOptions.iPictureQuality));
       
  2406     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() iPictureRate: %f"), aOptions.iPictureRate));
       
  2407     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() iQualityTemporalTradeoff: %f"), aOptions.iQualityTemporalTradeoff));
       
  2408     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() iLatencyQualityTradeoff: %f"), aOptions.iLatencyQualityTradeoff));
       
  2409 
       
  2410     if ( !StateRequiresDynamicSetting() )
       
  2411     	{
       
  2412         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() illegal state for dynamic settings")));
       
  2413     	User::Leave(KErrNotReady);
       
  2414     	}
       
  2415 
       
  2416 	// Handle new bitrate value:
       
  2417     if ( (aOptions.iBitrate < KCMRMinAcceptedBitRate) || ((iVideoCodecData->LevelForMMS()) && (aOptions.iBitrate > iVideoCodecData->MaxBitRate())) )
       
  2418         {// check that values are reasonable; check max bitrate only when the level is expected to be used for MMS
       
  2419         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() illegal bitrate")));
       
  2420         User::Leave(KErrArgument);
       
  2421         }
       
  2422     CCMRRecorderBase::SetTargetBitRateL(aOptions.iBitrate);
       
  2423     // inform the max bitrate to the sink
       
  2424     User::LeaveIfError( iOutput->SetMaxVideoBitRate( aOptions.iBitrate ) );
       
  2425     //inform the estimated average bitrate to sink; use a HW-specific scaler to estimate the average
       
  2426     TReal videoBitrateScaler = 0;
       
  2427     if ( iConfig )
       
  2428     	{
       
  2429         videoBitrateScaler = iConfig->PluginSettings().iCMRAvgVideoBitRateScaler;
       
  2430     	}
       
  2431     if ( videoBitrateScaler == 0 )
       
  2432     	{// make sure we never get scaler value 0 (ends up Div0 error)
       
  2433     	videoBitrateScaler = KCMRAvgVideoBitRateScaler;
       
  2434     	}
       
  2435     TInt br = static_cast<TInt>(aOptions.iBitrate*videoBitrateScaler);
       
  2436     User::LeaveIfError( iOutput->SetAverageVideoBitRate( br ) );
       
  2437 
       
  2438 
       
  2439     //Handle new framerate value:
       
  2440     if ( (aOptions.iPictureRate <= 0) || (aOptions.iPictureRate > iVideoCodecData->MaxFrameRate(iFrameSize)) )
       
  2441         {// check that values are reasonable
       
  2442         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() illegal frame rate, %f"), aOptions.iPictureRate));
       
  2443         User::Leave(KErrArgument);
       
  2444         }
       
  2445     if ( aOptions.iPictureRate <= iMaxFrameRate4GivenSize ) // actually iMaxFrameRate4GivenSize is valid only after prepare
       
  2446         {// encoding frame rate is always the requested one
       
  2447         iEncodingFrameRate = aOptions.iPictureRate;        // requested rate looks ok
       
  2448         }
       
  2449     else if ( iEncodingFrameRate < iMaxFrameRate4GivenSize )
       
  2450         {// too high rate requested, but the current rate is still lower than max possible, so we can set the rate higher anyway
       
  2451         iEncodingFrameRate = static_cast<TReal32>(iMaxFrameRate4GivenSize);
       
  2452         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL(), requested rate is too high for the used encoder, but set it to this rate: %f"), iMaxFrameRate4GivenSize));
       
  2453         }
       
  2454     if ( !iNightMode )
       
  2455         {// store the requested rate also, to be taken into use in the next prepare
       
  2456         iRequestedFrameRate = aOptions.iPictureRate;
       
  2457         }
       
  2458     if ( iEncodingFrameRate > iSourceFrameRate )
       
  2459         {// can't be higher than capture rate, limit it
       
  2460         iEncodingFrameRate = iSourceFrameRate;
       
  2461         }
       
  2462 
       
  2463     iRateControlOptions = aOptions;
       
  2464     iRateControlOptions.iPictureRate = iEncodingFrameRate;
       
  2465     if ( iDevVideoRec )
       
  2466     	{
       
  2467         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() settings stored and sending them to Devvideo.")));
       
  2468         iDevVideoRec->SetRateControlOptions(0, iRateControlOptions); // only base layer (layer 0) supported
       
  2469     	}
       
  2470     else
       
  2471     	{
       
  2472         PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() no DevVideoRec! Leaving KErrNotReady -18")));
       
  2473     	User::Leave(KErrNotReady);
       
  2474     	}
       
  2475     PRINT((_L("CCMRVideoRecorder::SetVideoRateControlOptionsL() out")));
       
  2476     }
       
  2477 
       
  2478 // ---------------------------------------------------------
       
  2479 // CCMRVideoRecorder::GetVideoRateControlOptionsL
       
  2480 // Get video rate control options
       
  2481 // (other items were commented in a header).
       
  2482 // ---------------------------------------------------------
       
  2483 //
       
  2484 void CCMRVideoRecorder::GetVideoRateControlOptionsL(TRateControlOptions& aOptions)
       
  2485     {
       
  2486     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() in")));
       
  2487     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() TBitrateControlType iControl: %d"), iRateControlOptions.iControl));
       
  2488     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() iBitrate: %d"), iRateControlOptions.iBitrate));
       
  2489     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() iPictureQuality: %d"), iRateControlOptions.iPictureQuality));
       
  2490     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() iPictureRate: %f"), iRateControlOptions.iPictureRate));
       
  2491     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() iQualityTemporalTradeoff: %f"), iRateControlOptions.iQualityTemporalTradeoff));
       
  2492     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() iLatencyQualityTradeoff: %f"), iRateControlOptions.iLatencyQualityTradeoff));
       
  2493 
       
  2494     if ( !StateRequiresDynamicSetting() )
       
  2495         {
       
  2496         PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() illegal state for dynamic settings")));
       
  2497         User::Leave(KErrNotReady);
       
  2498         }
       
  2499     aOptions = iRateControlOptions;
       
  2500     PRINT((_L("CCMRVideoRecorder::GetVideoRateControlOptionsL() out")));
       
  2501     }
       
  2502 
       
  2503 
       
  2504 // ---------------------------------------------------------
       
  2505 // CCMRVideoRecorder::SetPreferredVideoEncoderL
       
  2506 // Set video encoder using its UID. Usage optional.
       
  2507 // (other items were commented in a header).
       
  2508 // ---------------------------------------------------------
       
  2509 //
       
  2510 void CCMRVideoRecorder::SetPreferredVideoEncoderL(TUid& aEncoder)
       
  2511     {
       
  2512     PRINT((_L("CCMRVideoRecorder::SetPreferredVideoEncoderL() in")));
       
  2513     iPreferredEncoderUID = aEncoder;
       
  2514 
       
  2515     if ( iPreferredEncoderUID != KNullUid )
       
  2516         {// We have preferred encoder UID from client - override encoder search and use it instead.
       
  2517         PRINT((_L("CCMRVideoRecorder::SetPreferredVideoEncoderL() skipping encoder search. Using API user encoder: %d "), iPreferredEncoderUID.iUid));
       
  2518         iAvailableVideoEncoders.Reset();
       
  2519         iAvailableVideoEncoders.AppendL(iPreferredEncoderUID);
       
  2520         UpdateSupportedVideoFrameSizesRates();
       
  2521         }
       
  2522 
       
  2523     PRINT((_L("CCMRVideoRecorder::SetPreferredVideoEncoderL() out")));
       
  2524     }
       
  2525 
       
  2526 // ---------------------------------------------------------
       
  2527 // CCMRVideoRecorder::SetPreferredVideoEncapsulationL
       
  2528 // Set video encoder output format encapsulation. Usage optional.
       
  2529 // (other items were commented in a header).
       
  2530 // ---------------------------------------------------------
       
  2531 //
       
  2532 void CCMRVideoRecorder::SetPreferredVideoEncapsulationL(TVideoDataUnitEncapsulation aCapsulation)
       
  2533     {
       
  2534     PRINT((_L("CCMRVideoRecorder::SetPreferredVideoEncapsulationL() in")));
       
  2535     iPreferredEncapsulation = aCapsulation;
       
  2536     iPreferredEncapsulationSet = ETrue;
       
  2537     PRINT((_L("CCMRVideoRecorder::SetPreferredVideoEncapsulationL() out")));
       
  2538     }
       
  2539 
       
  2540 // ---------------------------------------------------------
       
  2541 // CCMRVideoRecorder::SetSegmentTargetSize
       
  2542 // Set video segment target size
       
  2543 // (other items were commented in a header).
       
  2544 // ---------------------------------------------------------
       
  2545 //
       
  2546 void CCMRVideoRecorder::SetSegmentTargetSizeL(TUint aLayer, TUint aSizeBytes, TUint aSizeMacroblocks)
       
  2547     {
       
  2548     PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() in")));
       
  2549     PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() aLayer: %d"), aLayer));
       
  2550     PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() aSizeBytes: %d"), aSizeBytes));
       
  2551     PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() aSizeMacroblocks: %d"), aSizeMacroblocks));
       
  2552 
       
  2553     if ( !StateRequiresDynamicSetting() )
       
  2554         {
       
  2555         PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() illegal state for dynamic settings")));
       
  2556         User::Leave(KErrNotReady);
       
  2557         }
       
  2558 
       
  2559     if ( iDevVideoRec )
       
  2560         {
       
  2561         PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() sending SetSegmentTargetSize to Devvideo.")));
       
  2562         iDevVideoRec->SetSegmentTargetSize(aLayer, aSizeBytes, aSizeMacroblocks); // only base layer (layer 0) supported
       
  2563         }
       
  2564     else
       
  2565         {
       
  2566         PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() no DevVideoRec! Leaving KErrNotReady -18")));
       
  2567         User::Leave(KErrNotReady);
       
  2568         }
       
  2569     PRINT((_L("CCMRVideoRecorder::SetSegmentTargetSize() out")));
       
  2570     }
       
  2571 
       
  2572 // ---------------------------------------------------------
       
  2573 // CCMRVideoRecorder::AdjustTimeStampsL
       
  2574 // Adjust time stamps of video
       
  2575 // (other items were commented in a header).
       
  2576 // ---------------------------------------------------------
       
  2577 //
       
  2578 void CCMRVideoRecorder::AdjustTimeStampsL(const TInt aAdjustmentMs)
       
  2579     {
       
  2580     if ( State() != EStateRecording )
       
  2581         {
       
  2582         PRINT((_L("CCMRVideoRecorder::AdjustTimeStampsL() wrong state")));
       
  2583         User::Leave( KErrNotReady );
       
  2584         }
       
  2585 
       
  2586     iAdjustmentTimeUs = TInt64( aAdjustmentMs * 1000 );
       
  2587 
       
  2588     PRINT((_L("CCMRVideoRecorder::AdjustTimeStampsL() by %d us"),I64INT(iAdjustmentTimeUs)));
       
  2589     }
       
  2590 
       
  2591 
       
  2592 // ---------------------------------------------------------
       
  2593 // CCMRVideoRecorder::MvsoReserveComplete
       
  2594 // Called by camera API when camera API has been reserved
       
  2595 // for exclusive use
       
  2596 // (other items were commented in a header).
       
  2597 // ---------------------------------------------------------
       
  2598 //
       
  2599 void CCMRVideoRecorder::MvsoReserveComplete(TInt aError)
       
  2600     {
       
  2601     PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() in")));
       
  2602 
       
  2603     // Should not be called, if we use direct capture mode
       
  2604     if (iDirectCapture)
       
  2605         {
       
  2606         VRASSERT(0);
       
  2607         }
       
  2608 
       
  2609     // need to set this already here if returns unsuccesfully, to enable error handling when encoder init completes
       
  2610     iSourceInitComplete = ETrue;
       
  2611 
       
  2612     if ( iEncoderInitComplete && (iErrorCode != KErrNone) )
       
  2613         {
       
  2614         // there was an error in the encoder initialisation, but the reporting was
       
  2615         // waiting for the completion of the source initialisation => report it now
       
  2616         PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() but error in video encoder: %d"), iErrorCode));
       
  2617         DoSendEventToClient( KCMREncoderInitError, iErrorCode );
       
  2618         iErrorCode = KErrNone;
       
  2619         return;
       
  2620         }
       
  2621 
       
  2622     if ( aError != KErrNone )
       
  2623         {
       
  2624         if ( iEncoderInitComplete )
       
  2625             {
       
  2626             PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() with error: %d"), aError));
       
  2627             DoSendEventToClient( KCMRCameraReserveError, aError );
       
  2628             }
       
  2629         else
       
  2630             {
       
  2631             // report only when encoder is completed too
       
  2632             PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() with error: %d, but must wait for encoder init completion"), aError));
       
  2633             iErrorCode = aError;
       
  2634             }
       
  2635         return;
       
  2636         }
       
  2637 
       
  2638     TInt error;
       
  2639 
       
  2640     TRAP(error, iSource->PrepareCaptureL(iVideoFormat, iSizeIndex, iRateIndex,
       
  2641                                          iNumCameraBuffers, KCMRNumFramesInCameraBuffer));
       
  2642 
       
  2643     PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() camera prepared, error %d"),error));
       
  2644     if ( error != KErrNone )
       
  2645         {
       
  2646         if ( iEncoderInitComplete )
       
  2647             {
       
  2648             DoSendEventToClient( KCMRCameraPrepareError, error );
       
  2649             }
       
  2650         else
       
  2651             {
       
  2652             // report only when encoder is completed too
       
  2653             iErrorCode = error;
       
  2654             }
       
  2655         return;
       
  2656         }
       
  2657 
       
  2658 
       
  2659     if ( iEncoderInitComplete )
       
  2660         {
       
  2661         SetState(EStateReadyToRecord);
       
  2662 
       
  2663         // everything ok, inform observer that we are prepared.
       
  2664         DoSendEventToClient( KCMRPrepareComplete, KErrNone );
       
  2665         }
       
  2666 
       
  2667     PRINT((_L("CCMRVideoRecorder::MvsoReserveComplete() out")));
       
  2668     }
       
  2669 
       
  2670 
       
  2671 // ---------------------------------------------------------
       
  2672 // CCMRVideoRecorder::MvsoFrameBufferReady
       
  2673 // Called by camera API when a frame (or several frames)
       
  2674 // has been captured
       
  2675 // (other items were commented in a header).
       
  2676 // ---------------------------------------------------------
       
  2677 //
       
  2678 void CCMRVideoRecorder::MvsoFrameBufferReady(MFrameBuffer* aFrameBuffer, TInt aError)
       
  2679     {
       
  2680     // Should not be called, if we use direct capture mode
       
  2681     if (iDirectCapture)
       
  2682         {
       
  2683         VRASSERT(0);
       
  2684         }
       
  2685 
       
  2686     if ( aError != KErrNone || aFrameBuffer == NULL )
       
  2687         {
       
  2688         // some errors, inform observer and return
       
  2689         DoSendEventToClient( KCMRCameraCaptureError, aError );
       
  2690         if ( aFrameBuffer )
       
  2691             {
       
  2692             // in case of errors, aFrameBuffer may be NULL
       
  2693             aFrameBuffer->Release();
       
  2694             }
       
  2695         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady with error %d"), aError));
       
  2696         return;
       
  2697         }
       
  2698 
       
  2699     PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady in %x, frame & time & systemdrift\t%d\t%d\t%d"),aFrameBuffer,
       
  2700                                                                                        aFrameBuffer->iIndexOfFirstFrameInBuffer,
       
  2701                                                                                        I64INT(aFrameBuffer->iElapsedTime.Int64()),
       
  2702                                                                                        I64INT(iSystemClockDelta.Int64())
       
  2703                                                                                        ));
       
  2704 
       
  2705 #ifdef VIDEO_FILE_OUTPUT
       
  2706 
       
  2707     // Write the frame to a file for testing purposes
       
  2708     TInt error = KErrNone;
       
  2709     TRAPD(error2, error = iOutputFile.Write( *(aFrameBuffer->DataL(0)) ));
       
  2710 
       
  2711     // release frame
       
  2712     aFrameBuffer->Release();
       
  2713 
       
  2714     if (error != KErrNone || error2 != KErrNone)
       
  2715         {
       
  2716         DoSendEventToClient( KCMRRunTimeError, error );
       
  2717         }
       
  2718 
       
  2719 
       
  2720 #else
       
  2721     // the real deal
       
  2722 
       
  2723     if ( (State() != EStateRecording) || (iErrorCode != KErrNone) )
       
  2724         {
       
  2725         // we are paused or stopping or there was an error => return the framebuffer immediately
       
  2726         // if system clock has been changed during pause take that account in future frame timestamp calculations.
       
  2727         if ( (((aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64()) < iLatestAbsoluteTimeStamp.Int64()) ||
       
  2728              ((aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64()) > (iLatestAbsoluteTimeStamp.Int64() + 2*iSourceFrameInterval))) &&
       
  2729              (aFrameBuffer->iIndexOfFirstFrameInBuffer == iPreviousCameraFrameIndex + 1) )
       
  2730              {
       
  2731              // something has changed system clock during pause, add cumulatively to drift delta.
       
  2732              iSystemClockDelta = (iLatestAbsoluteTimeStamp.Int64() + iSourceFrameInterval) -
       
  2733                                  (aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64())
       
  2734                                  + iSystemClockDelta.Int64();
       
  2735 
       
  2736              PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady() System time change: aFrameBuffer->iElapsedTime = %d, iSystemClockDelta = %d, iLatestAbsoluteTimeStamp = %d, iSourceFrameInterval = %d"),
       
  2737                                                                                               I64INT(aFrameBuffer->iElapsedTime.Int64()),
       
  2738                                                                                               I64INT(iSystemClockDelta.Int64()),
       
  2739                                                                                               I64INT(iLatestAbsoluteTimeStamp.Int64()),
       
  2740                                                                                               iSourceFrameInterval));
       
  2741              }
       
  2742 
       
  2743         iLatestAbsoluteTimeStamp = aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64();
       
  2744         iPreviousCameraFrameIndex = aFrameBuffer->iIndexOfFirstFrameInBuffer;
       
  2745         aFrameBuffer->Release();
       
  2746         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady() not recording, skip this one")));
       
  2747         return;
       
  2748         }
       
  2749 
       
  2750 
       
  2751 #if ( defined (__WINS__) || defined (__WINSCW__) )
       
  2752     if ( iEncoderInputQueueLength > 0 )
       
  2753         {
       
  2754         // Too many pictures already in the encoder's input queue - skip this one. In Wins the criteria is more strict since performance is lower
       
  2755         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady() - encoder already has one frame under processing, skip this one")));
       
  2756         iPreviousCameraFrameIndex = aFrameBuffer->iIndexOfFirstFrameInBuffer;
       
  2757         aFrameBuffer->Release();
       
  2758         return;
       
  2759         }
       
  2760 #else
       
  2761     if ( iEncoderInputQueueLength >= KCMRMaxPreEncoderBufferPictures )
       
  2762         {
       
  2763         // Too many pictures already in the encoder's input queue - skip this one
       
  2764         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady() - Encoder input/output queue(s) already full, must skip a captured frame")));
       
  2765         iPreviousCameraFrameIndex = aFrameBuffer->iIndexOfFirstFrameInBuffer;
       
  2766         aFrameBuffer->Release();
       
  2767         return;
       
  2768         }
       
  2769 #endif
       
  2770 
       
  2771     // Regulate timestamp to avoid too small or too large variations
       
  2772 
       
  2773     // use frame index instead of associated buffer timestamp, since timestamps may be
       
  2774     // less accurate and may cause rounding problems when converted to e.g. H.263 TRs
       
  2775     TInt64 frameTimeStamp;
       
  2776     frameTimeStamp = TInt64((aFrameBuffer->iIndexOfFirstFrameInBuffer - iDriftFrameSkipCount + iAddedFrameDurationCount) * 1E6/iSourceFrameRate + 0.5);   // use accurate division here since rounded value in multiplication multiplies also the rounding error
       
  2777 
       
  2778     // However, relying purely on frameindex causes drifting if the used source framerate value here is not exactly
       
  2779     // the camera input rate. Hence we need to do some adjustments.
       
  2780     // The frameindex may also be exclude skipped frames, but that should considered a bug in camera drivers, although the Camera API spec is not fully unambiguous about this
       
  2781     TInt64 expectedNewTimeStamp;
       
  2782     if ( iNumberOfCapturedFrames > 0 )
       
  2783         {
       
  2784         expectedNewTimeStamp = iLatestAbsoluteTimeStamp.Int64() + iSourceFrameInterval;
       
  2785         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), expectedNewTimeStamp (abs)\t%d\t"),I64INT(expectedNewTimeStamp)));
       
  2786         }
       
  2787     else
       
  2788         {
       
  2789         //first frame
       
  2790         expectedNewTimeStamp = 0;
       
  2791         iDriftFrameSkipCount = 0;
       
  2792         iAddedFrameDurationCount = 0;
       
  2793         iPreviousCameraFrameIndex = 0;
       
  2794         }
       
  2795 
       
  2796     TInt frameDropCount = aFrameBuffer->iIndexOfFirstFrameInBuffer - iPreviousCameraFrameIndex - 1;
       
  2797     iPreviousCameraFrameIndex = aFrameBuffer->iIndexOfFirstFrameInBuffer;
       
  2798     //
       
  2799     // Handle case where camera has dropped frames.
       
  2800     //
       
  2801     if ( frameDropCount > 0 )
       
  2802         {// Camera dropped frame
       
  2803         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), Camera dropped %d frame(s), drift from expected: \t%d\t"),
       
  2804                                                 frameDropCount,
       
  2805                                                 I64INT((frameTimeStamp - expectedNewTimeStamp ))));
       
  2806         frameTimeStamp = expectedNewTimeStamp + (frameDropCount*iSourceFrameInterval);
       
  2807         }
       
  2808 	//
       
  2809 	// Handle case where camera frame timestamp is more than previous encoded timestamp + specified camera frame duration.
       
  2810 	//
       
  2811     else if ( aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64() > expectedNewTimeStamp )
       
  2812         {
       
  2813         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), adjusted timestamp since it was greater than expected timestamp and we have delayed timestamps earlier\t%d\t"),I64INT((expectedNewTimeStamp - frameTimeStamp))));
       
  2814         // we have adjusted timestamps more to positive direction (delayed timestamps), try to compensate it now
       
  2815         // if camera frames have drifted more than 1 frame duration increase frame time stamp with one frame duration (as if frame dropped).
       
  2816         if ((aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64() - expectedNewTimeStamp) > iSourceFrameInterval )
       
  2817         	{
       
  2818         	iAddedFrameDurationCount++;
       
  2819         	PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), Camera timestamp has drifted more than 1 frame duration - adding 1 frame duration to timestamp from now on!\t%d\t"), iAddedFrameDurationCount ));
       
  2820         	expectedNewTimeStamp = iLatestAbsoluteTimeStamp.Int64() + 2*iSourceFrameInterval;
       
  2821             PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), new expectedNewTimeStamp (abs)\t%d\t"),I64INT(expectedNewTimeStamp)));
       
  2822         	}
       
  2823         frameTimeStamp = expectedNewTimeStamp;
       
  2824         }
       
  2825 	//
       
  2826 	// Handles case where camera frame timestamp is less than previous encoded frame timestamp
       
  2827 	// * happens when Camera is producing higher FPS that target FPS causing frame timestamp to drift below calculated cumulative recording time.
       
  2828 	//
       
  2829     else if ( aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64() < iLatestAbsoluteTimeStamp.Int64() )
       
  2830         {
       
  2831         // frame with the timestamp of this frame was already encoded
       
  2832         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), drift between expected and frame buffer timestamp more than 1 frame duration, dropping frame!")));
       
  2833         iDriftFrameSkipCount++;
       
  2834         aFrameBuffer->Release();
       
  2835         return;
       
  2836         }
       
  2837 	//
       
  2838 	// Handle case where (camera frame index * framerate) is less than camera frame timestamp - specified camera frame duration
       
  2839 	// * happens when Camera is skipping frames without extra increase in frame index count.
       
  2840 	//
       
  2841     else if ( frameTimeStamp < ( (aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64()) - iSourceFrameInterval ) )
       
  2842         {
       
  2843         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), adjusted timestamp since frame counter was too small compared to elapsed time: difference\t%d\t"),I64INT(aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64() - frameTimeStamp)));
       
  2844         // frame numbers & elapsed time do not match, probably camera is skipping frames but doesn't know it / doesn't inform it to us
       
  2845         frameTimeStamp = Max( aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64(), expectedNewTimeStamp );
       
  2846         }
       
  2847     //
       
  2848     // Handle case where (camera frame index * framerate) is less than calculated estimated timestamp value for currect frame
       
  2849     // (based on previous encoded frame timestamp + specified camera frame duration)
       
  2850     //
       
  2851     else if ( frameTimeStamp < expectedNewTimeStamp )
       
  2852         {
       
  2853         // timestamp should not be too close to the previous timestamp (video codecs set max for framerate <=> min for ts diff)
       
  2854         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), adjusted timestamp since it was smaller than expected timestamp, difference\t%d\t"),I64INT(expectedNewTimeStamp - frameTimeStamp)));
       
  2855         frameTimeStamp = expectedNewTimeStamp;
       
  2856         }
       
  2857     else
       
  2858         {
       
  2859         // leave it as it is
       
  2860         }
       
  2861 
       
  2862     // for now we've been playing with absolute times, excluding all pauses & adjustments. Save this value as reference for determining timestamp for the next frame
       
  2863     iLatestAbsoluteTimeStamp = frameTimeStamp;
       
  2864 
       
  2865     if ( iAdjustmentTimeUs != 0 )
       
  2866         {
       
  2867         // at the moment, initial and pause values are in opposite direction (+/-)
       
  2868         // for initial adjustment:
       
  2869         // if audio is ahead (iAdjustmentTimeUs > 0) => video should fast forward (video timestamps should be increased),
       
  2870         // if audio is behind (iAdjustmentTimeUs < 0) => video should "pause" for a while (video timestamps should be decreased)
       
  2871         // note that we modify here the iPausedTime which is subtracted from aFrameBuffer->iElapsedTime, so these
       
  2872         // changes affect kind of reverse way
       
  2873 
       
  2874         if ( ( frameTimeStamp - (iTotalPausedTime.Int64() - iAdjustmentTimeUs) ) >= (iLatestUsedTimeStamp.Int64() + iSourceFrameInterval) )
       
  2875             {
       
  2876             // iAdjustmentTimeUs > 0 or < 0 but not too much < 0 so that the resulting timestamp won't be < (latest time stamp + sourceframeinterval)
       
  2877             iTotalPausedTime = iTotalPausedTime.Int64() - iAdjustmentTimeUs;
       
  2878             PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), adjusted paused time by %d us"), I64INT(iAdjustmentTimeUs)));
       
  2879             iAdjustmentTimeUs = 0;
       
  2880             }
       
  2881         else
       
  2882             {
       
  2883             // iAdjustmentTimeUs < 0 here, we should "pause" video (skip frames) until we reach the required time
       
  2884             // Skipping is needed to avoid the timestamps to skip back over already captured frames.
       
  2885             PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), skipped a frame due to time adjustment request %d; buffer->elapsedTime %d; latest time stamp %d"), I64INT(iAdjustmentTimeUs), I64INT(aFrameBuffer->iElapsedTime.Int64() + iSystemClockDelta.Int64()), I64INT(iLatestUsedTimeStamp.Int64()) ));
       
  2886             aFrameBuffer->Release();
       
  2887             return;
       
  2888             }
       
  2889         }
       
  2890 
       
  2891     // subtract the time we were paused
       
  2892     // (MSL assumes devvideorecord/hw device does this but we do it here)
       
  2893     TTimeIntervalMicroSeconds iPrevUsedTimeStamp = iLatestUsedTimeStamp;
       
  2894     iLatestUsedTimeStamp = frameTimeStamp - iTotalPausedTime.Int64();
       
  2895 
       
  2896     // Increment timestamp in case we dropped frames during pause
       
  2897     while(( iLatestUsedTimeStamp < iPrevUsedTimeStamp ) && ( iNumberOfCapturedFrames > 0 ))
       
  2898         {
       
  2899         PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady() incrementing timestamp by one frame")));
       
  2900         iLatestUsedTimeStamp = TTimeIntervalMicroSeconds( iLatestUsedTimeStamp.Int64() + iSourceFrameInterval );
       
  2901         }
       
  2902 
       
  2903     PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), iTotalPausedTime \t%d"), I64INT(iTotalPausedTime.Int64()) ));
       
  2904     PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady(), iLatestUsedTimeStamp (relative) & drift from elapsed time\t%d"), I64INT(iLatestUsedTimeStamp.Int64()) ));
       
  2905 
       
  2906     EncodeFrame(aFrameBuffer);
       
  2907 
       
  2908     PRINT((_L("CCMRVideoRecorder::MvsoFrameBufferReady, out")));
       
  2909     }
       
  2910 
       
  2911 
       
  2912 // ---------------------------------------------------------
       
  2913 // CCMRVideoRecorder::EncodeFrame
       
  2914 // Encodes the given video frame.
       
  2915 // (other items were commented in a header).
       
  2916 // ---------------------------------------------------------
       
  2917 //
       
  2918 void CCMRVideoRecorder::EncodeFrame(MFrameBuffer* aFrameBuffer)
       
  2919     {
       
  2920     PRINT((_L("CCMRVideoRecorder::EncodeFrame, in")));
       
  2921 
       
  2922     // Take a TVideoPicture into use
       
  2923     TVideoPicture* outputPicture = NULL;
       
  2924     if ( iCodingFifo->IsEmpty() )
       
  2925         {
       
  2926         // allocate a new
       
  2927         outputPicture = new TVideoPicture;
       
  2928         if ( outputPicture == NULL )
       
  2929             {
       
  2930             // out of memory, stop operation
       
  2931             DoSendEventToClient( KCMRRunTimeError, KErrNoMemory );
       
  2932             aFrameBuffer->Release();
       
  2933             return;
       
  2934             }
       
  2935         }
       
  2936     else
       
  2937         {
       
  2938         // take an old one from the queue
       
  2939         outputPicture = reinterpret_cast<TVideoPicture*>(iCodingFifo->Get());
       
  2940         }
       
  2941 
       
  2942     iNumberOfCapturedFrames++;
       
  2943 
       
  2944 #ifdef _DEBUG
       
  2945     TTime current;
       
  2946     current.UniversalTime();
       
  2947     TInt elapsedMs = I64INT((current.MicroSecondsFrom(iLastCapture).Int64())) / 1000;
       
  2948     iCumulativeCaptureTime += elapsedMs;
       
  2949     iAverageCaptureTime = TReal(iCumulativeCaptureTime) / TReal(iNumberOfCapturedFrames);
       
  2950 
       
  2951     PRINT((_L("CCMRVideoRecorder::EncodeFrame() recording time %d, ms since last: %d, average capture time: %4.2f"),
       
  2952         (I64INT(current.MicroSecondsFrom(iRecordStartTime).Int64())) / 1000,
       
  2953         elapsedMs,
       
  2954         iAverageCaptureTime));
       
  2955 
       
  2956     iLastCapture = current;
       
  2957     iEncodingStartTime.UniversalTime();
       
  2958 #endif
       
  2959 
       
  2960     // wrap captured frame to encoder input buffer
       
  2961     outputPicture->iData.iDataFormat = EYuvRawData;
       
  2962     outputPicture->iData.iDataSize.iWidth = iFrameSize.iWidth;
       
  2963     outputPicture->iData.iDataSize.iHeight = iFrameSize.iHeight;
       
  2964     TRAPD(err, (outputPicture->iData.iRawData = (TPtr8*)aFrameBuffer->DataL(0)));
       
  2965     if ( err != KErrNone )
       
  2966         {
       
  2967         // error, stop operation
       
  2968         DoSendEventToClient( KCMRRunTimeError, err );
       
  2969         aFrameBuffer->Release();
       
  2970         delete outputPicture;
       
  2971         return;
       
  2972         }
       
  2973 
       
  2974     outputPicture->iTimestamp = iLatestUsedTimeStamp;
       
  2975     outputPicture->iOptions = TVideoPicture::ETimestamp;
       
  2976     outputPicture->iUser = this;
       
  2977 
       
  2978 #ifdef _DEBUG__
       
  2979     TTime current;
       
  2980     current.UniversalTime();
       
  2981 
       
  2982 
       
  2983     PRINT((_L("CCMRVideoRecorder::EncodeFrame()\t%d"),
       
  2984         (I64INT(current.MicroSecondsFrom(iRecordStartTime).Int64())) ));
       
  2985 #endif
       
  2986 
       
  2987 
       
  2988     // Put the captured buffer to iSourceFifo
       
  2989     TRAP( err, iSourceFifo->PutL( reinterpret_cast<TAny*>(aFrameBuffer) ));
       
  2990     if ( err != KErrNone )
       
  2991         {
       
  2992         // out of memory, stop operation
       
  2993         DoSendEventToClient( KCMRRunTimeError, err );
       
  2994         aFrameBuffer->Release();
       
  2995         delete outputPicture;
       
  2996         return;
       
  2997         }
       
  2998 
       
  2999 
       
  3000     // give the frame to devVideoRec for encoding
       
  3001     iEncoderInputQueueLength++;
       
  3002     TRAP( err, iDevVideoRec->WritePictureL( outputPicture ) );
       
  3003     if ( err != KErrNone )
       
  3004         {
       
  3005         // error, stop operation, aFrameBuffer will be released from fifo when stopped
       
  3006         DoSendEventToClient( KCMRRunTimeError, err );
       
  3007         return;
       
  3008         }
       
  3009 
       
  3010     PRINT((_L("CCMRVideoRecorder::EncodeFrame, picture %x written to devvr"),outputPicture));
       
  3011 
       
  3012 #endif // #else if !VIDEO_FILE_OUTPUT
       
  3013     }
       
  3014 
       
  3015 
       
  3016 // ---------------------------------------------------------
       
  3017 // CCMRVideoRecorder::MdvroInitializeComplete
       
  3018 // Called by DevVideoRecord when its initalization is complete
       
  3019 // (other items were commented in a header).
       
  3020 // ---------------------------------------------------------
       
  3021 //
       
  3022 void CCMRVideoRecorder::MdvroInitializeComplete(TInt aError)
       
  3023     {
       
  3024     PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete(), error[%d]"), aError));
       
  3025 
       
  3026     if ( iDirectCapture )
       
  3027         {
       
  3028         // Since direct capture is used, it should be true. Actual init CAPI status is
       
  3029         // included to aError now.
       
  3030         iSourceInitComplete = ETrue;
       
  3031         }
       
  3032 
       
  3033     iEncoderInitComplete = ETrue;
       
  3034 
       
  3035     if ( iSourceInitComplete && (iErrorCode != KErrNone) )
       
  3036         {
       
  3037         // there was an error in the source initialisation, but the reporting was
       
  3038         // waiting for the completion of the encoder initialisation => report it now
       
  3039         PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() but camera reservation had error: %d"), iErrorCode));
       
  3040         DoSendEventToClient( KCMRCameraReserveError, iErrorCode );
       
  3041         iErrorCode = KErrNone;
       
  3042         return;
       
  3043         }
       
  3044 
       
  3045     if ( aError != KErrNone )
       
  3046         {
       
  3047         if ( aError == KErrHardwareNotAvailable && iVideoCodecHWAccelerated )
       
  3048             {
       
  3049             PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() - initialization of HW accelerated video encoder failed, retrying with ARM codec")));
       
  3050             // hw accel codec and init failed due to resource problems => retry with non-hw-accelerated
       
  3051             iEncoderInitComplete = EFalse;
       
  3052             PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() - initialization of HW accelerated video encoder failed, delete devvideo")));
       
  3053             if (iDevVideoRec)
       
  3054                 {
       
  3055                 delete iDevVideoRec;
       
  3056                 iDevVideoRec = NULL;
       
  3057                 }
       
  3058             TRAPD(err, iDevVideoRec = CMMFDevVideoRecord::NewL( *this ));
       
  3059             if ( err == KErrNone )
       
  3060                 {
       
  3061                 PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() - initialization of HW accelerated video encoder failed, new devvideo created")));
       
  3062                 TRAP(err,SetupEncoderL());
       
  3063                 if ( err == KErrNone )
       
  3064                     {
       
  3065                     // ok, continue waiting for the callback
       
  3066                     return;
       
  3067                     }
       
  3068                 else
       
  3069                     {
       
  3070                     // store the last error, to be used in the operations below
       
  3071                     aError = err;
       
  3072                     }
       
  3073                 }
       
  3074             else
       
  3075                 {
       
  3076                 // store the last error, to be used in the operations below
       
  3077                 PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() - initialization of HW accelerated video encoder failed, new devvideo creation failed.")));
       
  3078                 aError = err;
       
  3079                 }
       
  3080             }
       
  3081 
       
  3082         if ( iSourceInitComplete )
       
  3083             {
       
  3084             PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() with error: %d"), aError));
       
  3085             DoSendEventToClient( KCMREncoderInitError, aError );
       
  3086             }
       
  3087         else
       
  3088             {
       
  3089             // report only when source is completed too
       
  3090             PRINT((_L("CCMRVideoRecorder::MdvroInitializeComplete() with error: %d, but must wait for camera reserve completion"), aError));
       
  3091             iErrorCode = aError;
       
  3092             }
       
  3093         return;
       
  3094         }
       
  3095 
       
  3096     if ( aError == KErrNone )
       
  3097         {
       
  3098         // If Encoder initialized Ok, give other run-time settings
       
  3099         // 1. Give dynamic settings to encoder after initializing
       
  3100         if ( !iVideoCodecHWAccelerated && ( iDevVideoRec->NumComplexityLevels(iEncoderHWDeviceId) > 0 ) )
       
  3101             {
       
  3102             iVideoComplexity = iConfig->PluginSettings().iVideoComplexitySetting;
       
  3103             iDevVideoRec->SetComplexityLevel( iEncoderHWDeviceId, iVideoComplexity );
       
  3104             }
       
  3105         // HW codec-specific configuration is HW dependent, and hence outside the scope of Series 60
       
  3106 
       
  3107         // 2. Rate control options
       
  3108         if ( iEncodingFrameRate > iMaxFrameRate4GivenSize )
       
  3109             {
       
  3110             iEncodingFrameRate = static_cast<TReal32>(iMaxFrameRate4GivenSize);
       
  3111             }
       
  3112 
       
  3113         FillRateControlOptions( iRateControlOptions );
       
  3114         iDevVideoRec->SetRateControlOptions(0, iRateControlOptions); // only base layer (layer 0) supported
       
  3115         TRAPD(err,iVideoCodecData->SetPostInitParamsL(iDevVideoRec));
       
  3116         if ( err ) {}
       
  3117         // ignore the error, having some post init setting is not crucial
       
  3118 
       
  3119         }
       
  3120 
       
  3121     if ( iSourceInitComplete )
       
  3122         {
       
  3123         SetState(EStateReadyToRecord);
       
  3124 
       
  3125         // everything ok, inform observer that we are prepared.
       
  3126         DoSendEventToClient( KCMRPrepareComplete, KErrNone );
       
  3127         }
       
  3128     }
       
  3129 
       
  3130 
       
  3131 // ---------------------------------------------------------
       
  3132 // CCMRVideoRecorder::MdvroReturnPicture
       
  3133 // Called by DevVideoRecord when it does not need the given
       
  3134 // input frame anymore
       
  3135 // (other items were commented in a header).
       
  3136 // ---------------------------------------------------------
       
  3137 //
       
  3138 void CCMRVideoRecorder::MdvroReturnPicture(TVideoPicture* aPicture)
       
  3139     {
       
  3140 #ifdef _DEBUG
       
  3141     TTime current;
       
  3142     current.UniversalTime();
       
  3143 
       
  3144 
       
  3145     PRINT((_L("CCMRVideoRecorder::MdvroReturnPicture() time now\t%d"),
       
  3146         (I64INT(current.MicroSecondsFrom(iRecordStartTime).Int64())) ));
       
  3147 #endif
       
  3148 
       
  3149     // take oldest frame from fifo
       
  3150     VRASSERT( !iSourceFifo->IsEmpty() );// if empty, for some reason the buffer was already returned!!
       
  3151 
       
  3152     MFrameBuffer* buffer = reinterpret_cast<MFrameBuffer*>(iSourceFifo->Get());
       
  3153 
       
  3154     // check that its the oldest stored captured picture
       
  3155     TPtr8* tmp = NULL;
       
  3156     TRAPD(error, (tmp = static_cast<TPtr8*>(buffer->DataL(0))));
       
  3157     if ( tmp != aPicture->iData.iRawData )
       
  3158         {
       
  3159         // pictures are returned in different order than they were sent
       
  3160 		RPointerArray<MFrameBuffer> buffers;
       
  3161         buffers.Append(buffer);
       
  3162 
       
  3163         TUint i;
       
  3164         for ( i = 1; i < iNumCameraBuffers; i++ )
       
  3165             {
       
  3166             buffers.Append(reinterpret_cast<MFrameBuffer*>(iSourceFifo->Get()));
       
  3167 
       
  3168             TRAP(error, (tmp = static_cast<TPtr8*>(buffers[i]->DataL(0))));
       
  3169             if ( tmp == aPicture->iData.iRawData )
       
  3170                 {
       
  3171                 // Found it! Put the retrieved buffers back to the queue
       
  3172                 TInt err = KErrNone;
       
  3173                 TUint j;
       
  3174                 for ( j = 0; j < i; j++ )
       
  3175                     {
       
  3176                     TRAP( err, iSourceFifo->PutL( reinterpret_cast<TAny*>(buffers[j]) ));
       
  3177                     // This can't really fail since we just got the buffers from the fifo and in that case PutL doesn't allocate anything => can't leave
       
  3178                     VRASSERT( err == KErrNone );
       
  3179                     buffers[j] = NULL;
       
  3180                     }
       
  3181                 break;
       
  3182                 }
       
  3183             }
       
  3184         VRASSERT( i < iNumCameraBuffers );
       
  3185         buffer = buffers[i];
       
  3186         buffers.Close();
       
  3187         }
       
  3188 
       
  3189     // release captured buffer
       
  3190     PRINT((_L("CCMRVideoRecorder::MdvroReturnPicture() releasing %x"), buffer ));
       
  3191     buffer->Release();
       
  3192     buffer = NULL;
       
  3193 
       
  3194     iEncoderInputQueueLength--;
       
  3195 
       
  3196 
       
  3197     // save the picture holder to fifo
       
  3198     TRAPD( err, iCodingFifo->PutL( reinterpret_cast<TAny*>(aPicture) ));
       
  3199     if ( err != KErrNone )
       
  3200         {
       
  3201         // OOM, inform error and stop operation
       
  3202         DoSendEventToClient( KCMRRunTimeError, err );
       
  3203         delete aPicture;
       
  3204         return;
       
  3205         }
       
  3206     PRINT((_L("CCMRVideoRecorder::MdvroReturnPicture() stored %x"), aPicture ));
       
  3207     }
       
  3208 
       
  3209 
       
  3210 // ---------------------------------------------------------
       
  3211 // CCMRVideoRecorder::MdvroSupplementalInfoSent
       
  3212 // Called by DevVideoRecord when supplemental info (e.g.,
       
  3213 // VOL header) has been sent to the encoder
       
  3214 // (other items were commented in a header).
       
  3215 // ---------------------------------------------------------
       
  3216 //
       
  3217 void CCMRVideoRecorder::MdvroSupplementalInfoSent()
       
  3218     {
       
  3219     PRINT((_L("CCMRVideoRecorder::MdvroSupplementalInfoSent()")));
       
  3220     User::Panic(_L("CCMRVIDEORECORDER"), KErrGeneral);
       
  3221     }
       
  3222 
       
  3223 
       
  3224 // ---------------------------------------------------------
       
  3225 // CCMRVideoRecorder::MdvroNewBuffers
       
  3226 // Called by DevVideoRecord when new bitstream buffers are
       
  3227 // available for retrieval
       
  3228 // (other items were commented in a header).
       
  3229 // ---------------------------------------------------------
       
  3230 //
       
  3231 void CCMRVideoRecorder::MdvroNewBuffers()
       
  3232     {
       
  3233 	PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers() - START - iRequestStatus: 0x%08x"), iRequestStatus ));
       
  3234     PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers(), NumDataBuffers[%d]"), iDevVideoRec->NumDataBuffers() ));
       
  3235     iNumberOfEncodedFrames++;
       
  3236 
       
  3237     TVideoOutputBuffer* buffer = NULL;
       
  3238     for (;;)
       
  3239         {
       
  3240         TRAPD( err, ( buffer = iDevVideoRec->NextBufferL()));
       
  3241 
       
  3242         if ( err != KErrNone )
       
  3243             {
       
  3244             return;
       
  3245             }
       
  3246         if ( buffer == NULL )
       
  3247             {
       
  3248             break;
       
  3249             }
       
  3250 /*      TInt bufferSize = buffer->iData.Length();
       
  3251         TInt bufferTimeStamp = I64INT(buffer->iCaptureTimestamp.Int64());
       
  3252         OstTraceExt2( TRACE_PERFORMANCE, CCMRVIDEORECORDER_MDVRONEWBUFFERS, "CCMRVideoRecorder::MdvroNewBuffers %d %d", bufferSize, bufferTimeStamp );
       
  3253 */        
       
  3254         // enter restricted area
       
  3255         iMutexObj.Wait();
       
  3256         // store
       
  3257         PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers(), storing buffer: 0x%x, timestamp: high: %u low: %u"), buffer, I64HIGH(buffer->iCaptureTimestamp.Int64()),I64LOW(buffer->iCaptureTimestamp.Int64())));
       
  3258         iVideoOutputBufferInputQue.AddLast(*buffer);
       
  3259         iNumberOfVideoOutputBuffers++;
       
  3260 
       
  3261         // leave restricted area
       
  3262         iMutexObj.Signal();
       
  3263         }
       
  3264 
       
  3265     // enter restricted area
       
  3266     iMutexObj.Wait();
       
  3267     if ( iRequestStatus )
       
  3268         {
       
  3269     	PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers() - completing output request..." )));
       
  3270         iOutputThreadHandle.RequestComplete( iRequestStatus, KErrNone );
       
  3271         }
       
  3272     else
       
  3273         {
       
  3274         // else a new request has not been issued yet
       
  3275     	PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers() - skipping RequestComplete" )));
       
  3276         }
       
  3277     // leave restricted area
       
  3278     iMutexObj.Signal();
       
  3279 
       
  3280 	PRINT((_L("CCMRVideoRecorder::MdvroNewBuffers() - END - iRequestStatus: 0x%08x"), iRequestStatus ));
       
  3281     }
       
  3282 
       
  3283 
       
  3284 // ---------------------------------------------------------
       
  3285 // CCMRVideoRecorder::MdvroFatalError
       
  3286 // Called by devVideoRecord when a fatal error has occurred
       
  3287 // (other items were commented in a header).
       
  3288 // ---------------------------------------------------------
       
  3289 //
       
  3290 void CCMRVideoRecorder::MdvroFatalError(TInt aError)
       
  3291     {
       
  3292     PRINT((_L("CCMRVideoRecorder::MdvroFatalError(), error[%d]"), aError));
       
  3293 
       
  3294     // Since now don't touch DevVideo that expects only destruction from the client, otherwise panics..
       
  3295     iFatalError = ETrue;
       
  3296 
       
  3297     // Cancel returning buffers to DevVideo
       
  3298     iBufferReturnAO->Cancel();
       
  3299 
       
  3300     if ( iDevVideoRec )
       
  3301     	{
       
  3302     	delete iDevVideoRec;
       
  3303     	iDevVideoRec = NULL;
       
  3304     	}
       
  3305 
       
  3306     if ( State() == EStateStopping )
       
  3307         {
       
  3308         // error occurred while stopping => carry out the rest of stopping & inform client
       
  3309         SetState( EStateReadyToRecord );
       
  3310         DoSendEventToClient( KCMRRecordingComplete, aError );
       
  3311         }
       
  3312     else
       
  3313         {
       
  3314         // inform client
       
  3315         DoSendEventToClient( KCMRRunTimeError, aError );
       
  3316         iErrorCode = aError;
       
  3317         }
       
  3318     }
       
  3319 
       
  3320 
       
  3321 // ---------------------------------------------------------
       
  3322 // CCMRVideoRecorder::MdvroStreamEnd
       
  3323 // Called by devVideoRecord when all pictures have been processed
       
  3324 // (after InputEnd is called)
       
  3325 // (other items were commented in a header).
       
  3326 // ---------------------------------------------------------
       
  3327 //
       
  3328 void CCMRVideoRecorder::MdvroStreamEnd()
       
  3329     {
       
  3330     PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd() in")));
       
  3331 
       
  3332     // MdvroStreamEnd was called by devVideo without InputEnd
       
  3333     VRASSERT( iInputEnd );
       
  3334 
       
  3335     // get all available buffers from devvideo
       
  3336     PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd(), getting all encoded frames from DevVideo.")));                
       
  3337     TVideoOutputBuffer* buffer = NULL;
       
  3338     for (;;)
       
  3339         {
       
  3340         TRAPD( err, ( buffer = iDevVideoRec->NextBufferL()));
       
  3341         if ( err != KErrNone || buffer == NULL)
       
  3342             {
       
  3343             break;
       
  3344             }
       
  3345         // enter restricted area
       
  3346         iMutexObj.Wait();
       
  3347         // store
       
  3348         PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd(), storing buffer: 0x%x, timestamp:%d"), buffer, I64INT(buffer->iCaptureTimestamp.Int64())));                  
       
  3349         iVideoOutputBufferInputQue.AddLast(*buffer);
       
  3350         iNumberOfVideoOutputBuffers++;
       
  3351 
       
  3352         // leave restricted area
       
  3353         iMutexObj.Signal();
       
  3354         }
       
  3355     
       
  3356     PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd(), flushing written frames back to DevVideo.")));                
       
  3357     iBufferReturnAO->Flush();    
       
  3358     
       
  3359     // stop
       
  3360     if ( iDevVideoRec )
       
  3361     	{
       
  3362         PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd() iDevVideoRec->Stop called")));    	
       
  3363         iDevVideoRec->Stop();
       
  3364     	}
       
  3365 
       
  3366     iStreamEnd = ETrue;
       
  3367     
       
  3368     // set state & inform MR => it can return from stop
       
  3369     SetState( EStateReadyToRecord );
       
  3370 
       
  3371     // everything ok, inform observer that we are ready for a new recording (iStopping does it too, though).
       
  3372     DoSendEventToClient( KCMRRecordingComplete, KErrNone );
       
  3373 
       
  3374     PRINT((_L("CCMRVideoRecorder::MdvroStreamEnd() out")));
       
  3375     }
       
  3376 
       
  3377 
       
  3378 // -----------------------------------------------------------------------------
       
  3379 // CCMRVideoRecorder::RequestNewData
       
  3380 // Output active object is ready to accept new data
       
  3381 // (other items were commented in a header).
       
  3382 // -----------------------------------------------------------------------------
       
  3383 //
       
  3384 void CCMRVideoRecorder::RequestNewData(TRequestStatus& aStatus)
       
  3385     {
       
  3386 	PRINT((_L("CCMRVideoRecorder::RequestNewData() - START - aStatus: 0x%08x, iRequestStatus: 0x%08x"), &aStatus, iRequestStatus ));
       
  3387 
       
  3388     // enter restricted area
       
  3389     iMutexObj.Wait();
       
  3390 
       
  3391     iRequestStatus = &aStatus;
       
  3392 	aStatus = KRequestPending;
       
  3393 
       
  3394     // leave restricted area
       
  3395     iMutexObj.Signal();
       
  3396 
       
  3397 	PRINT((_L("CCMRVideoRecorder::RequestNewData() - END - aStatus: 0x%08x, iRequestStatus: 0x%08x"), &aStatus, iRequestStatus ));
       
  3398     }
       
  3399 
       
  3400 
       
  3401 // -----------------------------------------------------------------------------
       
  3402 // CCMRVideoRecorder::RequestNewDataCancel
       
  3403 //
       
  3404 //
       
  3405 // -----------------------------------------------------------------------------
       
  3406 //
       
  3407 void CCMRVideoRecorder::RequestNewDataCancel(TRequestStatus& aStatus)
       
  3408     {
       
  3409 	PRINT((_L("CCMRVideoRecorder::RequestNewDataCancel() - START - aStatus: 0x%08x, iRequestStatus: 0x%08x"), &aStatus, iRequestStatus ));
       
  3410 
       
  3411     // enter restricted area
       
  3412     iMutexObj.Wait();
       
  3413 
       
  3414 	if ( &aStatus == iRequestStatus )
       
  3415 		{
       
  3416 		iOutputThreadHandle.RequestComplete( iRequestStatus, KErrCancel );
       
  3417 		}
       
  3418 
       
  3419     // leave restricted area
       
  3420     iMutexObj.Signal();
       
  3421 
       
  3422 	PRINT((_L("CCMRVideoRecorder::RequestNewDataCancel() - END - aStatus: 0x%08x, iRequestStatus: 0x%08x"), &aStatus, iRequestStatus ));
       
  3423 	}
       
  3424 
       
  3425 
       
  3426 // -----------------------------------------------------------------------------
       
  3427 // CCMRVideoRecorder::GetNextBuffer
       
  3428 // Output active object takes the next output buffer
       
  3429 // (other items were commented in a header).
       
  3430 // -----------------------------------------------------------------------------
       
  3431 //
       
  3432 CCMRMediaBuffer* CCMRVideoRecorder::GetNextBuffer()
       
  3433     {
       
  3434     PRINT((_L("CCMRVideoRecorder::GetNextBuffer() in") ));
       
  3435     if ( iDevVideoRec == NULL || iFatalError )
       
  3436         {
       
  3437         // probably we have not been opened yet
       
  3438         PRINT((_L("CCMRVideoRecorder::GetNextBuffer(), We have not been opened yet, or there's an error from devVideo")));
       
  3439         return NULL;
       
  3440         }
       
  3441 
       
  3442     if ( iDecSpecInfo )
       
  3443         {
       
  3444         // we have MPEG-4 decoder configuration information, it must be processed first
       
  3445         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() iDecSpecInfo") ));
       
  3446         iRemoveHeader = ETrue;
       
  3447         const TUint8* data = iDecSpecInfo->Ptr();
       
  3448         iDecSpecInfoLength = iDecSpecInfo->Length();
       
  3449 
       
  3450         CCMRMediaBuffer::TBufferType decSpecType = CCMRMediaBuffer::EVideoMPEG4DecSpecInfo;
       
  3451         if ( iVideoBufferType == CCMRMediaBuffer::EVideoH264NAL )
       
  3452             {// H.264 AVC NAL / GenericPayload encapsulation
       
  3453             decSpecType = CCMRMediaBuffer::EVideoH264NALDecSpecInfo;
       
  3454             }
       
  3455         else if ( iVideoBufferType == CCMRMediaBuffer::EVideoH264Bytestream )
       
  3456             {
       
  3457             decSpecType = CCMRMediaBuffer::EVideoH264BytestreamDecSpecInfo;
       
  3458             }
       
  3459 
       
  3460         // wrap the relevant data to CCMRMediaBuffer; iOutputSinkBuffer can't be != NULL here since it is created in ConstructL
       
  3461         iOutputSinkBuffer->Set( TPtrC8(data,iDecSpecInfoLength),
       
  3462                                 decSpecType,
       
  3463                                 iDecSpecInfoLength,
       
  3464                                 EFalse,
       
  3465                                 TTimeIntervalMicroSeconds(0) );
       
  3466 
       
  3467         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() decoder specific info to sink sent")));
       
  3468         return iOutputSinkBuffer;
       
  3469         }
       
  3470 
       
  3471     // enter restricted area
       
  3472     iMutexObj.Wait();
       
  3473     if (iNumberOfVideoOutputBuffers > 0)
       
  3474         {
       
  3475         iOutputVideoBuffer = iVideoOutputBufferInputQue.First();
       
  3476 
       
  3477         // Remove the picture from the list
       
  3478         iOutputVideoBuffer->iLink.Deque();
       
  3479         iNumberOfVideoOutputBuffers--;
       
  3480         // leave restricted area
       
  3481         iMutexObj.Signal();
       
  3482         }
       
  3483     else
       
  3484         {
       
  3485         // leave restricted area
       
  3486         PRINT((_L("CCMRVideoRecorder::GetNextBuffer()returning null, leave restricted area, iNumberOfVideoOutputBuffers == 0 %x"), this));
       
  3487         iMutexObj.Signal();
       
  3488         return NULL;
       
  3489         }
       
  3490 
       
  3491     PRINT((_L("CCMRVideoRecorder::GetNextBuffer() got [0x%x] from devvr"), iOutputVideoBuffer ));
       
  3492 
       
  3493     if ( iOutputVideoBuffer != NULL )
       
  3494         {
       
  3495         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() processing iOutputVideoBuffer") ));
       
  3496         TBool outputMediaBufferSet = EFalse;
       
  3497         if ( iRemoveHeader )
       
  3498             {
       
  3499             // check if we need to remove VOS+VO+VOL header from the bitstream, since it is stored in metadata, and
       
  3500             // having it in 2 places may cause interoperability problems
       
  3501             PRINT((_L("CCMRVideoRecorder::GetNextBuffer() remove extra header info") ));
       
  3502             iRemoveHeader = EFalse;
       
  3503             if ( iVideoBufferType == CCMRMediaBuffer::EVideoMPEG4 )
       
  3504                 {// MPEG-4
       
  3505                 RemoveSeqHeader( reinterpret_cast<TDesC8*>(&iOutputVideoBuffer->iData) );
       
  3506                 }
       
  3507             else if ( iVideoBufferType == CCMRMediaBuffer::EVideoH264NAL )
       
  3508                 {// H.264 AVC NAL /  EDuGenericPayload / NAL encapsulation
       
  3509                 // Removes SPS & PPS from first frame from encoder to avoid situation where its both in
       
  3510                 // .mp4 file metadata and in bitstream of video track.
       
  3511                 // Make sure buffer contains only one frame and rewrite encapsulation to make sure its ok.
       
  3512                 RemoveNalDecSpecInfoHeader( reinterpret_cast<TDesC8*>(&iOutputVideoBuffer->iData) );
       
  3513                 outputMediaBufferSet = ETrue;
       
  3514                 }
       
  3515             else if ( iVideoBufferType == CCMRMediaBuffer::EVideoH264Bytestream )
       
  3516                 {// H.264 AVC NAL /  EDuElementarystream / Bytestream
       
  3517                 // Removes SPS & PPS from first frame from encoder to avoid situation where its both in
       
  3518                 // .mp4 file metadata and in bitstream of video track.
       
  3519                 RemoveByteStreamDecSpecInfoHeader( reinterpret_cast<TDesC8*>(&iOutputVideoBuffer->iData) );
       
  3520                 outputMediaBufferSet = ETrue;
       
  3521                 }
       
  3522             }
       
  3523 
       
  3524         if ( !outputMediaBufferSet )
       
  3525         	{
       
  3526             // wrap the relevant data to CCMRMediaBuffer
       
  3527 	        iOutputSinkBuffer->Set( iOutputVideoBuffer->iData,
       
  3528 									iVideoBufferType,
       
  3529 									iOutputVideoBuffer->iData.Length(),
       
  3530 									iOutputVideoBuffer->iRandomAccessPoint,
       
  3531 									iOutputVideoBuffer->iCaptureTimestamp );
       
  3532         	}
       
  3533         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() iOutputSinkBuffer set") ));
       
  3534 
       
  3535 #ifdef _DEBUG__
       
  3536             TTime current;
       
  3537             current.UniversalTime();
       
  3538             TInt elapsedMs = (I64INT(current.MicroSecondsFrom(iEncodingStartTime).Int64())) / 1000;
       
  3539             iCumulativeEncodingTime += elapsedMs;
       
  3540             iAverageEncodingTime = TReal(iCumulativeEncodingTime) / TReal(iNumberOfEncodedFrames);
       
  3541 
       
  3542 
       
  3543             PRINT((_L("CCMRVideoRecorder::GetNextBuffer() %d, time consumed: %d, average encoding time: %4.2f"),
       
  3544                 (I64INT(current.MicroSecondsFrom(iRecordStartTime).Int64())) / 1000,
       
  3545                 (I64INT(current.MicroSecondsFrom(iEncodingStartTime).Int64())) / 1000,
       
  3546                 iAverageEncodingTime));
       
  3547 #endif
       
  3548 
       
  3549 #ifdef VIDEO_BS_FILE_OUTPUT
       
  3550             // Write the frame to a file for testing purposes; have to ignore possible errors
       
  3551             iOutputFile.Write(videoBuffer->iData);
       
  3552 #endif
       
  3553 
       
  3554         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() a buffer to sink sent with timestamp high: %u low: %u"),I64HIGH(iOutputVideoBuffer->iCaptureTimestamp.Int64()),I64LOW(iOutputVideoBuffer->iCaptureTimestamp.Int64())));        
       
  3555         return iOutputSinkBuffer;
       
  3556         }
       
  3557     else
       
  3558         {
       
  3559         PRINT((_L("CCMRVideoRecorder::GetNextBuffer() returning NULL - no new buffers in queue") ));
       
  3560         // no more new buffers in queue
       
  3561         return NULL;
       
  3562         }
       
  3563     }
       
  3564 
       
  3565 
       
  3566 // -----------------------------------------------------------------------------
       
  3567 // CCMRVideoRecorder::NumBuffersWaiting
       
  3568 // Return the number of buffers in the source
       
  3569 // (other items were commented in a header).
       
  3570 // -----------------------------------------------------------------------------
       
  3571 //
       
  3572 TInt CCMRVideoRecorder::NumBuffersWaiting()
       
  3573     {
       
  3574     if (iFatalError)
       
  3575         {
       
  3576         // NumDataBuffers() cannot be called since fatalError was reported
       
  3577         return 0;
       
  3578         }
       
  3579 
       
  3580     if ( iDecSpecInfo )
       
  3581         {
       
  3582         // decspecinfo is not counted in iNumberOfVideoOutputBuffers
       
  3583         return (iNumberOfVideoOutputBuffers+1);
       
  3584         }
       
  3585     else
       
  3586         {
       
  3587         return iNumberOfVideoOutputBuffers;
       
  3588         }
       
  3589     }
       
  3590 
       
  3591 
       
  3592 // -----------------------------------------------------------------------------
       
  3593 // CCMRVideoRecorder::LatestTimeStampL
       
  3594 // Return the latest time stamp from the input stream
       
  3595 // (other items were commented in a header).
       
  3596 // -----------------------------------------------------------------------------
       
  3597 //
       
  3598 void CCMRVideoRecorder::LatestTimeStampL(TTimeIntervalMicroSeconds& aTimeStamp) const
       
  3599     {
       
  3600     aTimeStamp = iLatestUsedTimeStamp;
       
  3601     }
       
  3602 
       
  3603 // -----------------------------------------------------------------------------
       
  3604 // CCMRVideoRecorder::DurationL
       
  3605 // Get duration of the recording (in practice the same as the latest time stamp)
       
  3606 // (other items were commented in a header).
       
  3607 // -----------------------------------------------------------------------------
       
  3608 //
       
  3609 void CCMRVideoRecorder::DurationL(TTimeIntervalMicroSeconds& aDuration) const
       
  3610     {
       
  3611     LatestTimeStampL( aDuration );
       
  3612     }
       
  3613 
       
  3614 // -----------------------------------------------------------------------------
       
  3615 // CCMRVideoRecorder::ReturnBuffer
       
  3616 // Output active object returns an emptied buffer
       
  3617 // (other items were commented in a header).
       
  3618 // -----------------------------------------------------------------------------
       
  3619 //
       
  3620 void CCMRVideoRecorder::ReturnBuffer(CCMRMediaBuffer* aBuffer)
       
  3621     {
       
  3622     PRINT((_L("CCMRVideoRecorder::ReturnBuffer() buffers 0x%x, 0x%x"),aBuffer, iOutputSinkBuffer));
       
  3623     VRASSERT( iOutputSinkBuffer == aBuffer );
       
  3624 
       
  3625     if ( iFatalError )
       
  3626         {
       
  3627         PRINT((_L("CCMRVideoRecorder::ReturnBuffer(), don't return anything, since there's an error from devVideo")));
       
  3628         iOutputVideoBuffer = NULL;
       
  3629         return;
       
  3630         }
       
  3631 
       
  3632     iOutputSinkBuffer = aBuffer;
       
  3633     if ( iDecSpecInfo )
       
  3634         {
       
  3635         delete iDecSpecInfo;
       
  3636         iDecSpecInfo = NULL;
       
  3637         // iOutputVideoBuffer is not used with decspecinfo
       
  3638         }
       
  3639     else
       
  3640         {
       
  3641         // normal case; iOutputVideoBuffer != NULL if functions are called in correct order
       
  3642         PRINT((_L("CCMRVideoRecorder::ReturnBuffer() iOutputVideoBuffer 0x%x"), iOutputVideoBuffer));
       
  3643         VRASSERT( iOutputVideoBuffer != NULL );
       
  3644         // store the buffer for sending from this thread
       
  3645         iBufferReturnAO->EnqueueReturnBuffer(iOutputVideoBuffer);
       
  3646 
       
  3647         iOutputVideoBuffer = NULL;
       
  3648         }
       
  3649     }
       
  3650 
       
  3651 
       
  3652 
       
  3653 // -----------------------------------------------------------------------------
       
  3654 // CCMRVideoRecorder::FillRateControlOptions
       
  3655 // Fill DevVideoRecord rate control options structure
       
  3656 // (other items were commented in a header).
       
  3657 // -----------------------------------------------------------------------------
       
  3658 //
       
  3659 void CCMRVideoRecorder::FillRateControlOptions( TRateControlOptions& aRC )
       
  3660     {
       
  3661     TRAPD(error,CCMRRecorderBase::TargetBitRateL((TInt&)(aRC.iBitrate)));
       
  3662 
       
  3663     // error can be ignored, it will never be != KErrNone at this stage
       
  3664     if (error != KErrNone)
       
  3665         {
       
  3666         VRASSERT( error == KErrNone );
       
  3667         }
       
  3668 
       
  3669     if ( iBitRateMode == EBitRateConstant )
       
  3670         {
       
  3671         aRC.iControl = EBrControlStream;
       
  3672         }
       
  3673     else
       
  3674         {
       
  3675         // Variable bitrate; rc.iBitrate is probably not needed but it gives now the upper limit
       
  3676         aRC.iControl = EBrControlNone;
       
  3677         }
       
  3678 
       
  3679     aRC.iPictureRate = iEncodingFrameRate;
       
  3680     // these are filled already in constructor:
       
  3681     //aRC.iPictureQuality
       
  3682     //aRC.iLatencyQualityTradeoff
       
  3683     //aRC.iQualityTemporalTradeoff
       
  3684     PRINT((_L("CCMRVideoRecorder::FillRateControlOptions() - framerate %f, bitrate %d"), aRC.iPictureRate, aRC.iBitrate));
       
  3685     }
       
  3686 
       
  3687 
       
  3688 // -----------------------------------------------------------------------------
       
  3689 // CCMRVideoRecorder::CheckExposure
       
  3690 // Check exposure from camera and adjust framerates if needed
       
  3691 // (other items were commented in a header).
       
  3692 // -----------------------------------------------------------------------------
       
  3693 //
       
  3694 void CCMRVideoRecorder::CheckExposure()
       
  3695     {
       
  3696     if ( iSource->GetExposure() == CCamera::EExposureNight )
       
  3697         {
       
  3698         iNightMode = ETrue;
       
  3699         iSourceFrameRate = iConfig->PluginSettings().iVideoNightFrameRate;
       
  3700         iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  3701 
       
  3702         // new framerate should be set to the encoder too
       
  3703         TRAPD(error, SetFrameRateL( iSourceFrameRate ));
       
  3704 
       
  3705         // error can be ignored, it will never be != KErrNone here
       
  3706         if (error != KErrNone)
       
  3707             {
       
  3708             VRASSERT( error == KErrNone );
       
  3709             }
       
  3710         }
       
  3711     else
       
  3712         {
       
  3713         // other modes don't affect to framerates, except if we switch back from night mode to normal
       
  3714         if ( iNightMode )
       
  3715             {
       
  3716             iSourceFrameRate = iRequestedFrameRate;
       
  3717             iSourceFrameInterval = convertFrameRateToInterval(iSourceFrameRate);
       
  3718 
       
  3719             // new framerate should be set to the encoder too
       
  3720             TRAPD(error,SetFrameRateL( iSourceFrameRate ));
       
  3721 
       
  3722             // error can be ignored, it will never be != KErrNone here
       
  3723             if (error != KErrNone)
       
  3724                 {
       
  3725                 VRASSERT( error == KErrNone );
       
  3726                 }
       
  3727 
       
  3728             iNightMode = EFalse;
       
  3729             }
       
  3730         }
       
  3731 
       
  3732     }
       
  3733 
       
  3734 
       
  3735 // -----------------------------------------------------------------------------
       
  3736 // CCMRVideoRecorder::UpdateSupportedFrameSizesRates
       
  3737 // Update supported video frames and sizes table from ECAM and MDF encoders.
       
  3738 // (other items were commented in a header).
       
  3739 // -----------------------------------------------------------------------------
       
  3740 //
       
  3741 void CCMRVideoRecorder::UpdateSupportedVideoFrameSizesRates()
       
  3742 	{
       
  3743 	PRINT((_L("CCMRVideoRecorder::UpdateSupportedFrameSizesRates() in")));
       
  3744 	iAvailableVideoFrameSizesRates.Reset();
       
  3745 
       
  3746 	if ( iAvailableVideoEncoders.Count() )
       
  3747 		{
       
  3748 	    for ( TInt i = 0 ; i < iAvailableVideoEncoders.Count(); i++ )
       
  3749 	        {
       
  3750 		    // encoder info for retrieving capabilities
       
  3751 		    CVideoEncoderInfo* encoderInfo = NULL;
       
  3752 	        PRINT((_L("CCMRVideoRecorder::UpdateSupportedFrameSizesRates() - getting info from a plugin index[%d] with Uid 0x%x"), i, iAvailableVideoEncoders[i].iUid ));
       
  3753 	        TRAPD(error, (encoderInfo = ReadEncoderInfoL(iAvailableVideoEncoders[i])) );
       
  3754 
       
  3755 	        if ( (encoderInfo != NULL) && (error == KErrNone))
       
  3756 	            {
       
  3757                 // Check directCapture support for current codec
       
  3758 				if ( encoderInfo->SupportsDirectCapture() )
       
  3759 					{
       
  3760 			        // check max framerate for given picture size
       
  3761 			        RArray<TPictureRateAndSize> rateAndSize = encoderInfo->MaxPictureRates();
       
  3762 			        for ( TUint j = 0; j < rateAndSize.Count(); j++ )
       
  3763 			            {
       
  3764 			            TPictureRateAndSize newSizeRate = rateAndSize[j];
       
  3765 						TInt addError = iAvailableVideoFrameSizesRates.InsertInOrder(newSizeRate, TLinearOrder<TPictureRateAndSize>(TLinearOrderFuncVideoSizeRate) );
       
  3766 						if (addError == KErrNone)
       
  3767 							{
       
  3768 							PRINT((_L("CCMRVideoRecorder::UpdateSupportedFrameSizesRates() - Added size: %d x %d, rate: %f"),
       
  3769 																					rateAndSize[j].iPictureSize.iWidth,
       
  3770 																					rateAndSize[j].iPictureSize.iHeight,
       
  3771 																					rateAndSize[j].iPictureRate));
       
  3772 							}
       
  3773 						}
       
  3774 					}
       
  3775 				delete encoderInfo;
       
  3776 	            }
       
  3777 	        }
       
  3778 		}
       
  3779 	PRINT((_L("CCMRVideoRecorder::UpdateSupportedFrameSizesRates() out")));
       
  3780 	}
       
  3781 
       
  3782 // -----------------------------------------------------------------------------
       
  3783 // CCMRVideoRecorder::DoSendEventToClient
       
  3784 // Send event to client
       
  3785 // (other items were commented in a header).
       
  3786 // -----------------------------------------------------------------------------
       
  3787 //
       
  3788 TInt CCMRVideoRecorder::DoSendEventToClient(TUid aEventType, TInt aErrorCode)
       
  3789     {
       
  3790     PRINT((_L("CCMRVideoRecorder::DoSendEventToClient(), aEventType %d"),aEventType.iUid));
       
  3791     TMMFEvent event(aEventType, aErrorCode);
       
  3792     return iEventHandler.SendEventToClient(event);
       
  3793     }
       
  3794 
       
  3795 
       
  3796 // -----------------------------------------------------------------------------
       
  3797 // CCMRVideoRecorder::ReturnBufferToDevVR
       
  3798 // CCMRReturnAO uses this function to return buffer to DevVideoRecord
       
  3799 // (other items were commented in a header).
       
  3800 // -----------------------------------------------------------------------------
       
  3801 //
       
  3802 void CCMRVideoRecorder::ReturnBufferToDevVR(TVideoOutputBuffer* aBuffer)
       
  3803     {
       
  3804     PRINT((_L("CCMRVideoRecorder::ReturnBufferToDevVR() in buffer: 0x%x, timestamp: high: %u low: %u"), aBuffer, I64HIGH(aBuffer->iCaptureTimestamp.Int64()),I64LOW(aBuffer->iCaptureTimestamp.Int64())));
       
  3805     if (iDevVideoRec)
       
  3806     	{
       
  3807         iDevVideoRec->ReturnBuffer(aBuffer);
       
  3808     	}
       
  3809     PRINT((_L("CCMRVideoRecorder::ReturnBufferToDevVR() out")));
       
  3810     }
       
  3811 
       
  3812 
       
  3813 // -----------------------------------------------------------------------------
       
  3814 // CCMRVideoRecorder::RemoveSeqHeader( TDesC8* aVideoBuffer )
       
  3815 // RemoveSeqHeader remove MPEG4 decoder configuration info (VOS+VO+VOL header)
       
  3816 // from the 1st video packet (it is saved in metadata, and duplication not allowed)
       
  3817 // Returns: TInt number of bytes removed
       
  3818 // -----------------------------------------------------------------------------
       
  3819 //
       
  3820 TInt CCMRVideoRecorder::RemoveSeqHeader( TDesC8* aVideoBuffer )
       
  3821     {
       
  3822     // MPEG-4 VOP header == the 1st element in the buffer to not remove
       
  3823     const TUint8 KHeader[4] = {0x00, 0x00, 0x01, 0xb6};
       
  3824     const TUint KSampleLength = 4;
       
  3825 
       
  3826     TPtr8* buffer = reinterpret_cast<TPtr8*>(aVideoBuffer);
       
  3827     // Bitstream start point
       
  3828     const TUint8* data = buffer->Ptr();
       
  3829     TUint headerLength;
       
  3830     TBool iFound = EFalse;
       
  3831 
       
  3832     // Search for VOP start code
       
  3833     for ( headerLength = 0; headerLength < (buffer->Length() - (KSampleLength - 1)); headerLength++ )
       
  3834         {
       
  3835         if ( (data[headerLength] == KHeader[0])
       
  3836             && (data[headerLength+1] == KHeader[1])
       
  3837             && (data[headerLength+2] == KHeader[2])
       
  3838             && (data[headerLength+3] == KHeader[3]) )
       
  3839             {
       
  3840             // VOP start code is found => video data starts from here
       
  3841             iFound = ETrue;
       
  3842             break;
       
  3843             }
       
  3844         }
       
  3845 
       
  3846     if ( (headerLength > 0) && iFound )
       
  3847         {
       
  3848         // adjust ptr & length depending which is longer VOP header location or earlier iDecSpecInfoLength length
       
  3849         if ( iDecSpecInfoLength && (iDecSpecInfoLength <= headerLength ) )
       
  3850 	        {
       
  3851 	        buffer->Delete(0,iDecSpecInfoLength);
       
  3852 	        }
       
  3853         else
       
  3854 	        {
       
  3855 			buffer->Delete(0,headerLength);
       
  3856 	        }
       
  3857         }
       
  3858     return headerLength;
       
  3859     }
       
  3860 
       
  3861 // -----------------------------------------------------------------------------
       
  3862 // CCMRVideoRecorder::RemoveNalDecSpecInfoHeader( TDesC8* aVideoBuffer )
       
  3863 // Removes decoder configuration info (SPS & PPS) from first NAL encapsulated H.264/AVC video buffer
       
  3864 // from encoder to avoid situation where its both in .mp4 file metadata and in bitstream of video track.
       
  3865 // Makes sure buffer contains only one frame and rewrite encapsulation to make sure its ok.
       
  3866 // -----------------------------------------------------------------------------
       
  3867 //
       
  3868 TInt CCMRVideoRecorder::RemoveNalDecSpecInfoHeader( TDesC8* aVideoBuffer )
       
  3869 	{
       
  3870 	// H.264 AVC NAL /  EDuGenericPayload / NAL encapsulation
       
  3871 
       
  3872     // Get reference to the buffer
       
  3873     TPtr8* ptr = reinterpret_cast<TPtr8*>(aVideoBuffer);
       
  3874     // Bitstream start point
       
  3875     TPtr8& buffer(*ptr);
       
  3876     TInt frameStart = 0;
       
  3877     TInt frameSize = 0;
       
  3878     TInt offset = 0;
       
  3879     TInt bufType = 0;
       
  3880     TInt i=0;
       
  3881     TInt totalNALLength = 0;
       
  3882     TInt firstCopiedNAL = 0;
       
  3883     TInt nalCount = 0;
       
  3884     RArray<TInt> nalSizes;
       
  3885     RArray<TInt> nalStarts;
       
  3886 
       
  3887     PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() in, length: %d "), buffer.Length() ));
       
  3888 
       
  3889 	// There should be enough data for the NAL header + frame
       
  3890     if ( buffer.Length() > 12 )
       
  3891         {
       
  3892         // Offset to the end and get NAL unit count
       
  3893         offset = buffer.Length()-4; //last 4 bytes are the NAL unit count
       
  3894         nalCount = TInt(buffer[offset]) +
       
  3895                   (TInt(buffer[offset + 1]) << 8) +
       
  3896                   (TInt(buffer[offset + 2]) << 16) +
       
  3897                   (TInt(buffer[offset + 3]) << 24);
       
  3898 
       
  3899         for(i=0; i<nalCount; i++)
       
  3900             {//go through all NAL units in buffer
       
  3901             // Offset to the start of NAL Unit infos
       
  3902             offset = buffer.Length()-4-(8*nalCount); // 4 is the NAL unit count at end of buffer, 8 bytes used per NAL Unit for FrameStartOffset and FrameSize.
       
  3903 
       
  3904             // Get frame start offset
       
  3905             offset += 8*i;
       
  3906             frameStart = TInt(buffer[offset]) +
       
  3907                         (TInt(buffer[offset + 1]) << 8) +
       
  3908                         (TInt(buffer[offset + 2]) << 16) +
       
  3909                         (TInt(buffer[offset + 3]) << 24);
       
  3910 
       
  3911             PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() NAL unit %d frame start: %d "), i, frameStart ));
       
  3912 
       
  3913             // Get frame size
       
  3914             offset += 4;
       
  3915             frameSize = TInt(buffer[offset]) +
       
  3916                        (TInt(buffer[offset + 1]) << 8) +
       
  3917                        (TInt(buffer[offset + 2]) << 16) +
       
  3918                        (TInt(buffer[offset + 3]) << 24);
       
  3919 
       
  3920            PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() NAL unit %d frame size: %d "), i, frameSize ));
       
  3921            bufType = buffer[frameStart] & 0x1F;
       
  3922            PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() NAL unit %d type: %d "), i, bufType ));
       
  3923            if ( bufType != 7 && //SPS
       
  3924                 bufType != 8 )//PPS
       
  3925                {
       
  3926                // we found first NAL unit that isn't SPS or PPS
       
  3927                nalSizes.Append(frameSize);
       
  3928                if (firstCopiedNAL==0)
       
  3929                    {
       
  3930                    firstCopiedNAL = frameStart;
       
  3931                    }
       
  3932                nalStarts.Append(frameStart-firstCopiedNAL);               
       
  3933                totalNALLength = frameStart+frameSize-firstCopiedNAL;
       
  3934                PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() new total length: %d, padding: %d "), totalNALLength, totalNALLength%4 ));
       
  3935                totalNALLength += totalNALLength%4;
       
  3936                }
       
  3937            }
       
  3938 
       
  3939         // The buffer should have enough space for the new NAL header
       
  3940 
       
  3941         // We need to write a new NAL header just after the frame end
       
  3942         PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() writing new header.")));
       
  3943         offset = firstCopiedNAL + totalNALLength;
       
  3944         
       
  3945         if ( (offset + nalSizes.Count()*8 + 4) > buffer.Length() ) 
       
  3946             {
       
  3947             PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() Fatal error, cannot create header, non-align 32bit encoder output buffer.")));
       
  3948             VRASSERT(0);            
       
  3949             }
       
  3950 
       
  3951         for (TInt j=0; j<nalSizes.Count(); j++)
       
  3952             {
       
  3953             PRINT((_L("CCMRVideoRecorder::RemoveNalDecSpecInfoHeader() new header, unit: %d, start: %d, size: %d."), j, nalStarts[j], nalSizes[j] ));            
       
  3954             // Write NAL unit start position
       
  3955             buffer[offset + 0] = TUint8(nalStarts[j] & 0xff);
       
  3956             buffer[offset + 1] = TUint8((nalStarts[j] >> 8) & 0xff);
       
  3957             buffer[offset + 2] = TUint8((nalStarts[j] >> 16) & 0xff);
       
  3958             buffer[offset + 3] = TUint8((nalStarts[j] >> 24) & 0xff);
       
  3959 
       
  3960             // Write NAL unit size
       
  3961             offset +=4;
       
  3962             buffer[offset + 0] = TUint8(nalSizes[j] & 0xff);
       
  3963             buffer[offset + 1] = TUint8((nalSizes[j] >> 8) & 0xff);
       
  3964             buffer[offset + 2] = TUint8((nalSizes[j] >> 16) & 0xff);
       
  3965             buffer[offset + 3] = TUint8((nalSizes[j] >> 24) & 0xff);
       
  3966 
       
  3967             offset +=4;
       
  3968             }
       
  3969 
       
  3970         // Write the number of NAL units
       
  3971         buffer[offset + 0] = TUint8(nalSizes.Count() & 0xff);;
       
  3972         buffer[offset + 1] = TUint8((nalSizes.Count() >> 8) & 0xff);;
       
  3973         buffer[offset + 2] = TUint8((nalSizes.Count() >> 16) & 0xff);
       
  3974         buffer[offset + 3] = TUint8((nalSizes.Count() >> 24) & 0xff);
       
  3975         }
       
  3976 
       
  3977     // Get a pointer to the position where the frame starts
       
  3978     TPtrC8 tmp( (buffer.Ptr() + firstCopiedNAL), (totalNALLength + (nalSizes.Count()*8) + 4) );
       
  3979 
       
  3980     // Set output media buffer
       
  3981     iOutputSinkBuffer->Set( tmp, CCMRMediaBuffer::EVideoH264NAL,
       
  3982                             tmp.Length(), iOutputVideoBuffer->iRandomAccessPoint,
       
  3983                             iOutputVideoBuffer->iCaptureTimestamp );
       
  3984 
       
  3985     nalSizes.Close();
       
  3986     nalStarts.Close();
       
  3987     return firstCopiedNAL;
       
  3988     }
       
  3989 
       
  3990 // -----------------------------------------------------------------------------
       
  3991 // CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader( TDesC8* aVideoBuffer )
       
  3992 // Removes decoder configuration info (SPS & PPS) from first bytestream encapsulated H.264/AVC video buffer
       
  3993 // from encoder to avoid situation where its both in .mp4 file metadata and in bitstream of video track.
       
  3994 // -----------------------------------------------------------------------------
       
  3995 //
       
  3996 TInt CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader( TDesC8* aVideoBuffer )
       
  3997 	{// H.264 AVC NAL /  EDuElementarystream / Bytestream
       
  3998     TInt skippedBytes = -1;
       
  3999     TInt bufType = 0;
       
  4000 
       
  4001     // Get reference to the buffer
       
  4002     TPtr8* buffer = reinterpret_cast<TPtr8*>(aVideoBuffer);
       
  4003     // Bitstream start point
       
  4004     const TUint8* data = buffer->Ptr();
       
  4005 
       
  4006     PRINT((_L("CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader() in, length: %d "), buffer->Length() ));
       
  4007 
       
  4008     // check buffer for bytestream header and possible decSpecInfo (SPS & PPS)
       
  4009     for (TInt i=0; i+4< buffer->Length(); i++)
       
  4010     	{
       
  4011     	// check for bytestream encapsulation [00 00 00 01]
       
  4012     	if ( data[i] == 0 &&
       
  4013     		 data[i+1] == 0 &&
       
  4014     		 data[i+2] == 0 &&
       
  4015     		 data[i+3] == 1 )
       
  4016     		{
       
  4017     	    PRINT((_L("CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader() 0001 header at: %d "), i ));
       
  4018     		// search buffer that isn't SPS or PPS
       
  4019     		bufType = data[i+4] & 0x1F;
       
  4020     		PRINT((_L("CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader() buffer type: %d "), bufType ));
       
  4021     		if ( (bufType == 7 || //SPS
       
  4022     			  bufType == 8) && //PPS
       
  4023     			  skippedBytes == -1 )
       
  4024     		    {// we need to skip SPS and PPS so activate next if clause
       
  4025     			skippedBytes = 0;
       
  4026     		    }
       
  4027     		if ( bufType != 7 && //SPS
       
  4028                  bufType != 8 && //PPS
       
  4029                  skippedBytes == 0)
       
  4030     		    {// found first non SPS / PPS buffer content -> stop stripping here
       
  4031     			skippedBytes = i;
       
  4032     		    PRINT((_L("CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader() skipping: %d bytes"), skippedBytes ));
       
  4033     			}
       
  4034     		}
       
  4035     	}
       
  4036 /*
       
  4037     if (skippedBytes)
       
  4038         {
       
  4039         for (TInt j=0; j<skippedBytes;j++)
       
  4040             {
       
  4041             PRINT((_L("CCMRVideoRecorder::RemoveByteStreamDecSpecInfoHeader() skipping %d: %x "), j, data[j] ));
       
  4042             }
       
  4043         }
       
  4044 */
       
  4045     // Get a pointer to the position where the frame starts
       
  4046     TPtrC8 tmp(buffer->Ptr() + skippedBytes, buffer->Length() - skippedBytes);
       
  4047 
       
  4048     // Set output media buffer
       
  4049     iOutputSinkBuffer->Set( tmp, CCMRMediaBuffer::EVideoH264Bytestream,
       
  4050                             tmp.Length(), iOutputVideoBuffer->iRandomAccessPoint,
       
  4051                             iOutputVideoBuffer->iCaptureTimestamp );
       
  4052 
       
  4053     return skippedBytes;
       
  4054 	}
       
  4055 
       
  4056 // ---------------------------------------------------------
       
  4057 // CCMRVideoRecorder::CCMRReturnAO::NewL
       
  4058 // Two-phased constructor.
       
  4059 // ---------------------------------------------------------
       
  4060 //
       
  4061 CCMRVideoRecorder::CCMRReturnAO* CCMRVideoRecorder::CCMRReturnAO::NewL(CCMRVideoRecorder* aHost)
       
  4062     {
       
  4063     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::NewL(), In")))
       
  4064 
       
  4065     CCMRReturnAO* self = new (ELeave) CCMRReturnAO(aHost);
       
  4066     CleanupStack::PushL( self );
       
  4067     self->ConstructL();
       
  4068     CleanupStack::Pop();
       
  4069 
       
  4070     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::NewL(), Out")))
       
  4071     return self;
       
  4072     }
       
  4073 
       
  4074 // -----------------------------------------------------------------------------
       
  4075 // CCMRVideoRecorder::CCMRReturnAO::CCMRReturnAO
       
  4076 // Default constructor for CCMRReturnAO
       
  4077 // (other items were commented in a header).
       
  4078 // -----------------------------------------------------------------------------
       
  4079 //
       
  4080 CCMRVideoRecorder::CCMRReturnAO::CCMRReturnAO(CCMRVideoRecorder* aHost) :
       
  4081         CActive(EPriorityNormal),
       
  4082         iVideoOutputBufferReturnQue(_FOFF(TVideoOutputBuffer,iLink)),
       
  4083         iVideoOutputBufferReturnQueIter(iVideoOutputBufferReturnQue),
       
  4084         iHost(aHost)
       
  4085     {
       
  4086     CActiveScheduler::Add(this);
       
  4087     }
       
  4088 
       
  4089 // ---------------------------------------------------------
       
  4090 // CCMRVideoRecorder::CCMRReturnAO::ConstructL()
       
  4091 // Symbian 2nd phase constructor can leave.
       
  4092 // ---------------------------------------------------------
       
  4093 //
       
  4094 void CCMRVideoRecorder::CCMRReturnAO::ConstructL()
       
  4095     {
       
  4096     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::ConstructL() in")));
       
  4097     User::LeaveIfError(iMutexObj.CreateLocal());
       
  4098     iMutexCreated = ETrue;
       
  4099     User::LeaveIfError(iVideoThreadHandle.Open(RThread().Id()));
       
  4100     iThreadHandleOpened = ETrue;
       
  4101 
       
  4102     iStatus = KRequestPending;
       
  4103     SetActive();
       
  4104     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::ConstructL() out")));
       
  4105     }
       
  4106 
       
  4107 // -----------------------------------------------------------------------------
       
  4108 // CCMRVideoRecorder::CCMRReturnAO::~CCMRReturnAO
       
  4109 // Destructor for CCMRReturnAO
       
  4110 // (other items were commented in a header).
       
  4111 // -----------------------------------------------------------------------------
       
  4112 //
       
  4113 CCMRVideoRecorder::CCMRReturnAO::~CCMRReturnAO()
       
  4114     {
       
  4115     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::~CCMRReturnAO")));
       
  4116     if ( iMutexCreated )
       
  4117         {
       
  4118         iMutexObj.Close();
       
  4119         }
       
  4120     if ( iThreadHandleOpened )
       
  4121         {
       
  4122         iVideoThreadHandle.Close();
       
  4123         }
       
  4124     }
       
  4125 
       
  4126 // -----------------------------------------------------------------------------
       
  4127 // CCMRVideoRecorder::CCMRReturnAO::EnqueueReturnBuffer
       
  4128 // Enqueue TVideoOutputBuffer from controller thread to be returned to
       
  4129 // DevVideoRecord from this thread
       
  4130 // (other items were commented in a header).
       
  4131 // -----------------------------------------------------------------------------
       
  4132 //
       
  4133 void CCMRVideoRecorder::CCMRReturnAO::EnqueueReturnBuffer(TVideoOutputBuffer* aBuffer)
       
  4134     {
       
  4135     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::EnqueueReturnBuffer() in aBuffer=0x%x "), aBuffer));
       
  4136     // enter restricted area
       
  4137     iMutexObj.Wait();
       
  4138     iVideoOutputBufferReturnQue.AddLast(*aBuffer);
       
  4139     if ( iStatus == KRequestPending )
       
  4140         {
       
  4141         TRequestStatus* tmp = &iStatus;
       
  4142         iVideoThreadHandle.RequestComplete(tmp, KErrNone);
       
  4143         }
       
  4144     // leave restricted area
       
  4145     iMutexObj.Signal();
       
  4146     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::EnqueueReturnBuffer() out")));
       
  4147     }
       
  4148 
       
  4149 
       
  4150 // -----------------------------------------------------------------------------
       
  4151 // CCMRVideoRecorder::CCMRReturnAO::Flush
       
  4152 // Flush content of return queueu to DevVideo
       
  4153 // (other items were commented in a header).
       
  4154 // -----------------------------------------------------------------------------
       
  4155 //
       
  4156 void CCMRVideoRecorder::CCMRReturnAO::Flush()
       
  4157     {
       
  4158     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::Flush() in.")));
       
  4159     iMutexObj.Wait();
       
  4160     while (!iVideoOutputBufferReturnQue.IsEmpty())
       
  4161         {
       
  4162         // take the oldest buffer
       
  4163         TVideoOutputBuffer* tmp = iVideoOutputBufferReturnQue.First();
       
  4164         // Remove the picture from the list
       
  4165         tmp->iLink.Deque();
       
  4166         // send it to DevVR using the CCMRVideoRecorder object
       
  4167         iHost->ReturnBufferToDevVR(tmp);
       
  4168         tmp = NULL;
       
  4169         }
       
  4170     // leave restricted area
       
  4171     iMutexObj.Signal();
       
  4172     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::Flush() out")));
       
  4173     }
       
  4174 
       
  4175 // -----------------------------------------------------------------------------
       
  4176 // CCMRVideoRecorder::CCMRReturnAO::RunL
       
  4177 // Returns the queued buffers
       
  4178 // (other items were commented in a header).
       
  4179 // -----------------------------------------------------------------------------
       
  4180 //
       
  4181 void CCMRVideoRecorder::CCMRReturnAO::RunL()
       
  4182     {
       
  4183     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::RunL() - iStatus: %d"), iStatus.Int() ));
       
  4184     SetActive();
       
  4185     // enter restricted area
       
  4186     iMutexObj.Wait();
       
  4187     iStatus = KRequestPending;
       
  4188     while (!iVideoOutputBufferReturnQue.IsEmpty())
       
  4189         {
       
  4190         // take the oldest buffer
       
  4191         TVideoOutputBuffer* tmp = iVideoOutputBufferReturnQue.First();
       
  4192         // Remove the picture from the list
       
  4193         tmp->iLink.Deque();
       
  4194         // send it to DevVR using the CCMRVideoRecorder object
       
  4195         iHost->ReturnBufferToDevVR(tmp);
       
  4196         tmp = NULL;
       
  4197         }
       
  4198     // leave restricted area
       
  4199     iMutexObj.Signal();
       
  4200     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::RunL() out")));
       
  4201     }
       
  4202 
       
  4203 // -----------------------------------------------------------------------------
       
  4204 // CCMRVideoRecorder::CCMRReturnAO::RunError
       
  4205 // Handles errors from RunL
       
  4206 // (other items were commented in a header).
       
  4207 // -----------------------------------------------------------------------------
       
  4208 //
       
  4209 TInt CCMRVideoRecorder::CCMRReturnAO::RunError(TInt aError)
       
  4210     {
       
  4211     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::RunError")));
       
  4212     // currently RunL can't leave, but keep this here to remind the possible need in the future
       
  4213     if (aError != KErrNone)
       
  4214         {
       
  4215         PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::RunError() error %d"),aError));
       
  4216         }
       
  4217     return KErrNone;
       
  4218     }
       
  4219 
       
  4220 // -----------------------------------------------------------------------------
       
  4221 // CCMRVideoRecorder::CCMRReturnAO::DoCancel
       
  4222 // Cancels the active object
       
  4223 // (other items were commented in a header).
       
  4224 // -----------------------------------------------------------------------------
       
  4225 //
       
  4226 void CCMRVideoRecorder::CCMRReturnAO::DoCancel()
       
  4227     {
       
  4228     // Cancel the request
       
  4229     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::DoCancel() in")));
       
  4230     if ( iStatus == KRequestPending )
       
  4231         {
       
  4232         TRequestStatus *stat = &iStatus;
       
  4233         User::RequestComplete(stat, KErrCancel);
       
  4234         }
       
  4235     PRINT((_L("CCMRVideoRecorder::CCMRReturnAO::DoCancel() out")));
       
  4236     }
       
  4237 
       
  4238 // End of file