camcordermmfplugin/filecomposer/Src/CamC3GPDataSinkImp.cpp
changeset 0 9b3e960ffc8a
child 1 2d3e1993fb02
equal deleted inserted replaced
-1:000000000000 0:9b3e960ffc8a
       
     1 /*
       
     2 * Copyright (c) 2002-2006 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:  3GP file composer
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include <f32file.h>
       
    20 #include <mmf/server/mmffile.h>
       
    21 #include <sysutildomaincrkeys.h>	// for critical disk level CentralRepository keys
       
    22 #include <3gplibrary/mp4lib.h>
       
    23 #include "CamC3GPDataSink.h"
       
    24 #include "CamC3GPDataSinkImp.h"
       
    25 #include "CCMRMediaSink.h"
       
    26 #include "CCMRSupportedCodecs.h"
       
    27 
       
    28 #include <stdlib.h>
       
    29 #include <stdio.h>
       
    30 #include <string.h>
       
    31 #include <sys/unistd.h>
       
    32 
       
    33 // MACROS
       
    34 // Debug print macro
       
    35 #ifdef _DEBUG
       
    36 #include <e32svr.h>
       
    37 #define PRINT(x) RDebug::Print x
       
    38 #else
       
    39 #define PRINT(x)
       
    40 #endif
       
    41 
       
    42 // CONSTANTS
       
    43 const TUint   KVideoAverageBitRate   = 48000;     // Default average bitrate for video
       
    44 const TUint   KVideoMaxBitRate       = 64000;     // Default maximum bitrate for video
       
    45 const TUint   KVideoXResolution      = 176;       // Default width of video
       
    46 const TUint   KVideoYResolution      = 144;       // Default height of video
       
    47 const TUint   KVideoBufferSize       = 8192;      // Maximum video frame size
       
    48 const TUint   KAudioMaxFrameSize     = 32;        // Maximum AMR audio frame size
       
    49 const TUint   KAudioBufferNumber     = 10;        // Number of audio frames to be buffered
       
    50 const TUint   KVideoTimeScale        = 30000;     // Video timescale in the output file; use 30000 since it corresponds roughly to ~30 fps.
       
    51                                                   // 29970 would be exact for H.263, but it may not be exactly camera's baseframerate. And it may be harder for some players than 30000
       
    52                                                   // The most important is now that this value is in the same scale as used in MediaRecorder for Camera API framerate.
       
    53                                                   // If that is 15, then this should be 30000. But some other, e.g. 14.985 fps is used there, then it is better to change this one too.
       
    54 const TUint   KAudioTimeScale        = 8000;      // Audio timescale in the output file, safer to use the same value as sampling rate although makes the times more difficult to understand
       
    55 const TUint   KAudioFrameDuration    = 8*20;      // AMR frame is 20 ms, but timescale is 8000 => duration is 160 / 8000 s
       
    56 const TUint8  KAMRAudioFramesPerSample  = 10;     // Number of AMR audio frames per sample in the output file
       
    57 const TUint8  KAACAudioFramesPerSample  = 1;      // Number of AAC audio frames per sample in the output file
       
    58 const TUint   KAACDefaultSampleRate  = 16000;     // Default samplerate for AAC that is used as audio track timescale in case we get no audiobuffers, but audio codec is selected.
       
    59 const TUint16 KAudioModeSet          = 0x81ff;    // AMR modeset: all modes possible
       
    60 const TUint   KDiskSafetyLimit       = 400000;    // Amount of free disk space to leave unused
       
    61 const TReal   KMetaDataCoeff         = 1.03;      // Coefficient to estimate metadata amount
       
    62 const TInt    KFreeDiskSpaceCounter  = 10;        // Interval when to find out real free disk space
       
    63 const TUint   KFTYPSize              = 24;        // Size of FTYP box in bytes in 3GP files
       
    64 const TUint   KCamCMaxClipDurationInSecs = 5400;  // Maximun video clip duration in seconds
       
    65 const TInt    KLimitForLargeFileBuffers = 100000; // Bitrate limit to toggle to larger output file buffers in composer.
       
    66 const TInt    KDelayUseBitrates      = 3000000;   // Delay used in GetRemainingTime until function uses real file sizes instead of avarage bitrates.
       
    67 const TInt    KCamC3GPDeleteFileQueueGranularity  = 10; // Optimal value is the number of temporary files
       
    68 const TUint32 KCamC3GPMaximumFileSize = 4294967295UL; // max size for RFile
       
    69 
       
    70 _LIT(KTmpFileName, "\\system\\Temp\\CamcorderTMP");               // Temporary output file name
       
    71 
       
    72 // ============================ MEMBER FUNCTIONS ===============================
       
    73 
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CCamC3GPDataSink::NewL
       
    77 //
       
    78 // Sink constructor.
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 EXPORT_C CCamC3GPDataSink* CCamC3GPDataSink::NewL(M3GPDataSinkObserver *aObserver)
       
    82     {
       
    83 	CCamC3GPDataSinkImp* self = new (ELeave) CCamC3GPDataSinkImp();
       
    84 	CleanupStack::PushL(self);
       
    85 	self->ConstructL(aObserver);
       
    86 	CleanupStack::Pop();
       
    87 	return self;
       
    88     }
       
    89 
       
    90 
       
    91 // -----------------------------------------------------------------------------
       
    92 // CCamC3GPDataSinkImp::~CCamC3GPDataSinkImp
       
    93 //
       
    94 // Sink destructor.
       
    95 // -----------------------------------------------------------------------------
       
    96 //
       
    97 CCamC3GPDataSinkImp::~CCamC3GPDataSinkImp(void)
       
    98     {
       
    99     PRINT(_L("CCamC3GPDataSinkImp::~CCamC3GPDataSinkImp enter"));
       
   100     delete [] iVideoBuffer;
       
   101     delete [] iAudioBuffer;
       
   102 
       
   103     if ( iFileName != KNullDesC )
       
   104         {
       
   105         // we need to try to stop sink
       
   106         TInt error = KErrNone;
       
   107         TRAP(error, SinkStopL());
       
   108         iFileName = KNullDesC;
       
   109         }
       
   110 
       
   111     if (iMP4Handle)
       
   112         {
       
   113         MP4ComposeClose(iMP4Handle);
       
   114         iMP4Handle = NULL;
       
   115         }
       
   116 
       
   117     if (iFS)
       
   118         {
       
   119         iFS->Delete(iTmpFileName);
       
   120         iFS->Close();
       
   121         delete iFS;
       
   122         iFS = NULL;
       
   123         }
       
   124 
       
   125     iObserver = NULL;
       
   126     iMMFFile = NULL; // not owned
       
   127     iFile = NULL; // not owned
       
   128 
       
   129     // Delete the CIdle async file remover object
       
   130     delete iIdleDelete;
       
   131     iIdleDelete = 0;
       
   132 
       
   133     // Do async temp file deletion for rest of files
       
   134     if ( iDeleteFileQueue )
       
   135         {
       
   136         // Reset and destroy the file name pointers from queue (if any left).
       
   137         iDeleteFileQueue->ResetAndDestroy();
       
   138         }
       
   139     delete iDeleteFileQueue;
       
   140     iDeleteFileQueue = 0;
       
   141     PRINT(_L("CCamC3GPDataSinkImp::~CCamC3GPDataSinkImp exit"));
       
   142     }
       
   143 
       
   144 
       
   145 // -----------------------------------------------------------------------------
       
   146 // CCamC3GPDataSinkImp::ConstructL
       
   147 //
       
   148 // Symbian 2nd phase constructor.
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 void CCamC3GPDataSinkImp::ConstructL(M3GPDataSinkObserver *aObserver)
       
   152 	{
       
   153     PRINT(_L("CCamC3GPDataSinkImp::ConstructL enter"));
       
   154     iObserver = aObserver;
       
   155 
       
   156     iVideoBuffer = new (ELeave) TUint8[KVideoBufferSize];
       
   157     iVideoBufferSize = KVideoBufferSize;
       
   158 
       
   159     iAudioBuffer = new (ELeave) TUint8[KAudioMaxFrameSize * KAudioBufferNumber];
       
   160     iAudioBufferSize = KAudioMaxFrameSize * KAudioBufferNumber;
       
   161 
       
   162     iMP4Handle = NULL;
       
   163     iMMFFile = NULL;
       
   164 
       
   165     iFileName = KNullDesC;
       
   166 
       
   167     iBytesReceived = 0;
       
   168     iBytesOfMetadata = 0;
       
   169 
       
   170     iVideoXResolution = 0;
       
   171     iVideoYResolution = 0;
       
   172     iVideoAverageBitRate = -1;
       
   173     iVideoMaxBitRate = -1;
       
   174     iAudioAverageBitRate = -1;
       
   175 
       
   176     iBufferSize = 0;
       
   177     iFileCodecType = MP4_TYPE_NONE;
       
   178     iVideoTimestamp = 0;
       
   179     iVideoBufferTimestamp = -1;
       
   180     iFirstVideoFrameTimestamp = 0;
       
   181     iVideoRandomAccessPoint = EFalse;
       
   182     iVideoBufferRandomAccessPoint = EFalse;
       
   183     iVideoFrameDuration = 0;
       
   184     iVideoBufferFrameSize = 0;
       
   185     iVideoFrameNumber = 0;
       
   186     iVideoIntraFrameNumber = 0;
       
   187     iVideoDecSpecInfoSize = 0;
       
   188     iAudioDecSpecInfoSize = 0;
       
   189     iAudioBufferFrameSize = 0;
       
   190     iAudioFrameNumber = 0;
       
   191     iAudioFramesInBuffer = 0;
       
   192     iFreeDiskSpace = 0;
       
   193     iFreeDiskSpaceCounter = 0;
       
   194     iAvailableSpaceAtStart = 0;
       
   195     iAvarageEndTime = -1;
       
   196     iAudioAACFrameDuration = 0;
       
   197     iAudioAACSamplerate = 0;
       
   198     iAVCOutputLevel = 10;
       
   199     iCriticalDiskVal = 0;
       
   200 
       
   201     iSizeLimit = KCamC3GPMaximumFileSize; // max size for RFile
       
   202     iFileSizeLimitReached = EFalse;
       
   203     iDiskFull = EFalse;
       
   204     iFS = NULL;
       
   205 
       
   206     iDeleteFileQueue = new( ELeave ) RPointerArray<MP4FileName>( KCamC3GPDeleteFileQueueGranularity );
       
   207 
       
   208     // Idle priority Active object for async video temp file deletion
       
   209     iIdleDelete = CIdle::NewL( CActive::EPriorityIdle );
       
   210 
       
   211     PRINT(_L("CCamC3GPDataSinkImp::ConstructL exit"));
       
   212 	}
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // CCamC3GPDataSinkImp::OpenFileL
       
   216 //
       
   217 // Opens a 3GP file for writing.
       
   218 // -----------------------------------------------------------------------------
       
   219 //
       
   220 void CCamC3GPDataSinkImp::OpenFileL(CMMFFile* aMMFFile, TFourCC aAudioCodecType, const TDesC8& aVideoCodecType, TCamCSinkFileFormat aFileFormat )
       
   221     {
       
   222     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL CMMFFile enter")));
       
   223 
       
   224     TFileName aFileName;
       
   225     iMMFFile = aMMFFile;
       
   226     aFileName = iMMFFile->FullName();
       
   227 
       
   228     OpenFileL(aFileName, aAudioCodecType, aVideoCodecType, aFileFormat);
       
   229     }
       
   230 
       
   231 // -----------------------------------------------------------------------------
       
   232 // CCamC3GPDataSinkImp::OpenFileL
       
   233 //
       
   234 // Opens a 3GP file for writing.
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 void CCamC3GPDataSinkImp::OpenFileL(TFileName aFileName, TFourCC aAudioCodecType, const TDesC8& aVideoCodecType, TCamCSinkFileFormat aFileFormat)
       
   238     {
       
   239     MP4Err    error;
       
   240 
       
   241     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL TFileName enter")));
       
   242 
       
   243     if (iMP4Handle)
       
   244         {
       
   245         User::Leave(KErrGeneral);
       
   246         }
       
   247 
       
   248     iVideoBufferTimestamp = -1;     // reset duration information for new file
       
   249     iFirstVideoFrameTimestamp = 0;
       
   250     iAvailableSpaceAtStart = 0;
       
   251     iAvarageEndTime = -1;
       
   252     iVideoFrameNumber = 0;
       
   253     iVideoIntraFrameNumber = 0;
       
   254     iBytesReceived = 0;
       
   255     iAudioAACFrameDuration = 0;
       
   256     iAudioAACSamplerate = 0;
       
   257     iFileHandleExists = EFalse;
       
   258 
       
   259     iDiskFull = EFalse;
       
   260     iTmpFileName = KTmpFileName;
       
   261     iFileName = aFileName;
       
   262     TInt errorcode;
       
   263 
       
   264     if (!iFS) // Don't allocate new file server, if there is one already
       
   265         {
       
   266         iFS = new (ELeave) RFs;
       
   267 
       
   268         errorcode = iFS->Connect();
       
   269         if ( errorcode != KErrNone)
       
   270             {
       
   271             delete(iFS);
       
   272             iFS = NULL;
       
   273             User::Leave( errorcode );
       
   274             }
       
   275         }
       
   276 
       
   277     TParse fp;
       
   278     User::LeaveIfError(iFS->Parse(iFileName, fp));
       
   279     TPtrC driveletter = fp.Drive();
       
   280     TChar drl = driveletter[0];
       
   281     User::LeaveIfError(iFS->CharToDrive(drl, iDriveNumber));
       
   282 
       
   283     // Get critical level for this drive type
       
   284     TDriveInfo driveInfo;
       
   285     iFS->Drive(driveInfo, iDriveNumber);
       
   286 
       
   287     iCriticalDiskVal = 0;
       
   288 	if ( driveInfo.iType == EMediaRam ) // RAM drives have different critical levent than others
       
   289 		{
       
   290 		PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Asking disk critical level, memtype: EMediaRam")));
       
   291 		CRepository* repository = CRepository::NewLC( KCRUidDiskLevel );
       
   292 		User::LeaveIfError( repository->Get( KRamDiskCriticalLevel, iCriticalDiskVal ) );
       
   293 		PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Got disk critical level: %d"),iCriticalDiskVal ));
       
   294 		CleanupStack::PopAndDestroy( repository );
       
   295 		}
       
   296 	else // Some other media type
       
   297 		{
       
   298 		PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Asking disk critical level, memtype: other")));
       
   299 		CRepository* repository = CRepository::NewLC( KCRUidDiskLevel );
       
   300 		User::LeaveIfError( repository->Get( KDiskCriticalThreshold, iCriticalDiskVal ) );
       
   301 		PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Got disk critical level: %d"),iCriticalDiskVal ));
       
   302 		CleanupStack::PopAndDestroy( repository );
       
   303 		}
       
   304 
       
   305     errorcode = iFS->MkDirAll(fp.DriveAndPath());
       
   306     if ( (errorcode != KErrAlreadyExists ) && ( errorcode != KErrNone ) )
       
   307         {
       
   308         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Error creating output path: '%s', error: %d"), fp.DriveAndPath().Ptr(), errorcode ));
       
   309         User::Leave(errorcode);
       
   310         }
       
   311 
       
   312     errorcode = iFS->SetAtt( iFileName, KEntryAttNormal, KEntryAttReadOnly );
       
   313     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Deleting File: '%s'"), iFileName.Ptr()));
       
   314     errorcode = iFS->Delete(iFileName);
       
   315     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Deleting File Error: %d"), errorcode));
       
   316 
       
   317     if ( errorcode == KErrInUse && iMMFFile )
       
   318         {
       
   319         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL using rfiles")));
       
   320         iMMFFile->SinkPrimeL();
       
   321         iFile = &(iMMFFile->FileL());
       
   322         iFileHandleExists = ETrue;
       
   323         }
       
   324     else if ( ( errorcode != KErrNone ) && ( errorcode != KErrNotFound ) && ( errorcode != KErrPathNotFound ) )
       
   325         {
       
   326         User::Leave(errorcode);
       
   327         }
       
   328 
       
   329     iTmpFileName.Insert(0, fp.Drive());
       
   330     errorcode = iFS->SetAtt( iTmpFileName, KEntryAttNormal, KEntryAttReadOnly );
       
   331     errorcode = iFS->Delete(iTmpFileName);
       
   332     if ( ( errorcode != KErrNone ) && ( errorcode != KErrNotFound ) && ( errorcode != KErrPathNotFound ) )
       
   333     	{
       
   334         if ( errorcode == KErrInUse )
       
   335         	{
       
   336         	// use actual output filename incase other instance still running with temporary file.
       
   337             PRINT((_L("CCamC3GPDataSinkImp::OpenFileL temporary output file in use (-14). Using actual output filename instead.")));
       
   338         	iTmpFileName = aFileName;
       
   339             errorcode = iFS->SetAtt( iTmpFileName, KEntryAttNormal, KEntryAttReadOnly );
       
   340             errorcode = iFS->Delete(iTmpFileName);
       
   341             if ( ( errorcode != KErrNone ) && ( errorcode != KErrNotFound ) && ( errorcode != KErrPathNotFound ) )
       
   342             	{
       
   343             	User::Leave(errorcode);
       
   344             	}
       
   345         	}
       
   346         else
       
   347         	{
       
   348         	User::Leave(errorcode);
       
   349         	}
       
   350         }
       
   351 
       
   352     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Temp files cleared")));
       
   353 
       
   354     // Find used audio codec
       
   355     if ( ( aAudioCodecType == TFourCC(KCMRFourCCIdAMRNB) ) ) // AMR-NB
       
   356         {
       
   357         iFileCodecType |= MP4_TYPE_AMR_NB;
       
   358         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Audio codec: AMR-NB")));
       
   359         }
       
   360     else if ( aAudioCodecType == TFourCC(KCMRFourCCIdMPEG4AAC) ) // AAC
       
   361         {
       
   362         iFileCodecType |= MP4_TYPE_MPEG4_AUDIO;
       
   363         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Audio codec: AAC")));
       
   364         }
       
   365     else
       
   366         {
       
   367         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Audio codec: none")));
       
   368         // if audio codec is null we don't generate audiotrack to composed file.
       
   369         }
       
   370 
       
   371     // Find used video codec
       
   372     mp4_u8 videoLevel = 10;
       
   373 
       
   374     if ( aVideoCodecType == KNullDesC8 ) // No video codec set.
       
   375         {
       
   376         // filecomposer will always create videotrack, whether we get video frames or not.
       
   377         iFileCodecType |= MP4_TYPE_H263_PROFILE_0;
       
   378         }
       
   379     else
       
   380         {
       
   381         TBuf8<256> matchstring;
       
   382         matchstring = KCMRMimeTypeH263;
       
   383         matchstring += _L8( "*" );
       
   384 
       
   385         if ( ( aVideoCodecType.MatchF( matchstring ) != KErrNotFound ) ) // H.263
       
   386             {
       
   387             matchstring = KCMRMimeTypeH263Profile3;
       
   388             matchstring += _L8( "*" );
       
   389 
       
   390             if ( aVideoCodecType.MatchF( matchstring ) != KErrNotFound )
       
   391                 {
       
   392                 iFileCodecType |= MP4_TYPE_H263_PROFILE_3;   // H.263 profile 3
       
   393                 PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 profile 3")));
       
   394                 }
       
   395             else
       
   396                 {
       
   397                 iFileCodecType |= MP4_TYPE_H263_PROFILE_0;   // H.263 profile 0
       
   398                 PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 profile 0")));
       
   399                 }
       
   400             // check if level is indicated too
       
   401             matchstring = _L8("*level=*");
       
   402             if (aVideoCodecType.MatchF( matchstring ) != KErrNotFound )
       
   403                 {
       
   404                 // yes, there is, check what it is
       
   405                 if ( aVideoCodecType.MatchF( _L8("*level=10*") ) != KErrNotFound )
       
   406                     {
       
   407                     videoLevel = 10;
       
   408                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 10")));
       
   409                     }
       
   410                 else if ( aVideoCodecType.MatchF( _L8("*level=20*") ) != KErrNotFound )
       
   411                     {
       
   412                     videoLevel = 20;
       
   413                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 20")));
       
   414                     }
       
   415                 else if ( aVideoCodecType.MatchF( _L8("*level=30*") ) != KErrNotFound )
       
   416                     {
       
   417                     videoLevel = 30;
       
   418                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 30")));
       
   419                     }
       
   420                 else if ( aVideoCodecType.MatchF( _L8("*level=40*") ) != KErrNotFound )
       
   421                     {
       
   422                     videoLevel = 40;
       
   423                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 40")));
       
   424                     }
       
   425                 else if ( aVideoCodecType.MatchF( _L8("*level=45*") ) != KErrNotFound )
       
   426                     {
       
   427                     videoLevel = 45;
       
   428                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 45")));
       
   429                     }
       
   430                 else if ( aVideoCodecType.MatchF( _L8("*level=50*") ) != KErrNotFound )
       
   431                     {
       
   432                     videoLevel = 50;
       
   433                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 50")));
       
   434                     }
       
   435                 else
       
   436                     {
       
   437                     // assume 10
       
   438                     videoLevel = 10;
       
   439                     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Video codec: H.263 level 10")));
       
   440                     }
       
   441                 }
       
   442             }
       
   443         else // MPEG-4
       
   444             {
       
   445             matchstring = KCMRMimeTypeMPEG4V;
       
   446             matchstring += _L8( "*" );
       
   447 
       
   448             if ( aVideoCodecType.MatchF(matchstring) != KErrNotFound )
       
   449                 {
       
   450                 iFileCodecType |= MP4_TYPE_MPEG4_VIDEO;     // MPEG-4
       
   451                 }
       
   452             else // H.264 AVC
       
   453 	            {
       
   454 	            matchstring = KCMRMimeTypeH264AVC;
       
   455 	            matchstring += _L8( "*" );
       
   456 
       
   457 	            if ( aVideoCodecType.MatchF(matchstring) != KErrNotFound )
       
   458 	                {
       
   459                     iAVCOutputLevel = 10;
       
   460 		            // check if profile & level is indicated too
       
   461 		            matchstring = _L8("*profile-level-id=*");
       
   462 		            if (aVideoCodecType.MatchF( matchstring ) != KErrNotFound )
       
   463 		                {
       
   464 		                // yes, there is, check what it is
       
   465 	                    // Determine if other AVC profile is used:
       
   466                         matchstring = _L8( "*profile-level-id=42*" ); // Main Profile 
       
   467                         if (aVideoCodecType.MatchF( matchstring ) != KErrNotFound)
       
   468                             {
       
   469                             iFileCodecType |= MP4_TYPE_AVC_PROFILE_BASELINE;     // H.264 AVC Baseline profile found 
       
   470                             }
       
   471 	                    matchstring = _L8( "*profile-level-id=4D*" ); // Main Profile 
       
   472 	                    if (aVideoCodecType.MatchF( matchstring ) != KErrNotFound)
       
   473 	                        {
       
   474 	                        iFileCodecType |= MP4_TYPE_AVC_PROFILE_MAIN;     // H.264 AVC Main profile found 
       
   475 	                        }
       
   476 	                    matchstring = _L8( "*profile-level-id=64*" ); // High Profile 
       
   477 	                    if (aVideoCodecType.MatchF( matchstring ) != KErrNotFound)
       
   478 	                        {
       
   479 	                        iFileCodecType |= MP4_TYPE_AVC_PROFILE_HIGH;     // H.264 AVC Baseline profile found 
       
   480 	                        }
       
   481 		                
       
   482 	                    // Determine if other AVC level is used:
       
   483 		                if ( aVideoCodecType.MatchF( _L8("*00A*") ) != KErrNotFound )
       
   484 		                    {
       
   485 		                    iAVCOutputLevel = 10; 	// Level 1
       
   486 		                    }
       
   487 		                else if ( (aVideoCodecType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound) ||
       
   488                                   (aVideoCodecType.MatchF( _L8("*profile-level-id=4D500B*") ) != KErrNotFound) || 
       
   489                                   (aVideoCodecType.MatchF( _L8("*profile-level-id=644009*") ) != KErrNotFound) )
       
   490 		                    {
       
   491 		                    iAVCOutputLevel = 101; 	// Level 1b
       
   492 		                    }
       
   493                         else if ( (aVideoCodecType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound) ||
       
   494                                   (aVideoCodecType.MatchF( _L8("*profile-level-id=4D400B*") ) != KErrNotFound) || 
       
   495                                   (aVideoCodecType.MatchF( _L8("*profile-level-id=64400B*") ) != KErrNotFound) )
       
   496 		                    {
       
   497 		                    iAVCOutputLevel = 11;	// Level 1.1
       
   498 		                    }
       
   499 		                else if ( aVideoCodecType.MatchF( _L8("*00C*") ) != KErrNotFound )
       
   500 		                    {
       
   501 		                    iAVCOutputLevel = 12;	// Level 1.2
       
   502 		                    }
       
   503 		                else if ( aVideoCodecType.MatchF( _L8("*00D*") ) != KErrNotFound )
       
   504 		                    {
       
   505 		                    iAVCOutputLevel = 13;	// Level 1.3
       
   506 		                    }
       
   507 		                else if ( aVideoCodecType.MatchF( _L8("*014*") ) != KErrNotFound )
       
   508 		                    {
       
   509 		                    iAVCOutputLevel = 20;	// Level 2
       
   510 		                    }
       
   511                         else if ( aVideoCodecType.MatchF( _L8("*015*") ) != KErrNotFound )
       
   512                             {
       
   513                             iAVCOutputLevel = 21;   // Level 2.1
       
   514                             }
       
   515                         else if ( aVideoCodecType.MatchF( _L8("*016*") ) != KErrNotFound )
       
   516                             {
       
   517                             iAVCOutputLevel = 22;   // Level 2.2
       
   518                             }
       
   519                         else if ( aVideoCodecType.MatchF( _L8("*01E*") ) != KErrNotFound )
       
   520                             {
       
   521                             iAVCOutputLevel = 30;   // Level 3
       
   522                             }
       
   523                         else if ( aVideoCodecType.MatchF( _L8("*01F*") ) != KErrNotFound )
       
   524                             {
       
   525                             iAVCOutputLevel = 31;   // Level 3.1
       
   526                             }
       
   527                         else if ( aVideoCodecType.MatchF( _L8("*020*") ) != KErrNotFound )
       
   528                             {
       
   529                             iAVCOutputLevel = 32;   // Level 3.2
       
   530                             }
       
   531                         else if ( aVideoCodecType.MatchF( _L8("*028*") ) != KErrNotFound )
       
   532                             {
       
   533                             iAVCOutputLevel = 4;   // Level 4
       
   534                             }
       
   535 		                else
       
   536 		                    {
       
   537 		                    // assume level 1
       
   538 		                    PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Warning unknown video codec type - defaulting level 1.0")));
       
   539 		                    iAVCOutputLevel = 10;
       
   540 		                    }
       
   541 		                }
       
   542 	                }
       
   543 	            else
       
   544 		            {
       
   545     				PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Unsupported video codec type")));
       
   546 		            User::Leave(KErrArgument);
       
   547 		            }
       
   548 	            }
       
   549             }
       
   550         }
       
   551 
       
   552     if ( iFileHandleExists )
       
   553         {
       
   554         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL using rfile to open mp4handle")));
       
   555         error = MP4ComposeOpenFileHandle(&iMP4Handle, iFile, (TDriveNumber)iDriveNumber, iFileCodecType);
       
   556         }
       
   557     else
       
   558         {
       
   559         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL using descriptors to open mp4handle")));
       
   560         error = MP4ComposeOpen(&iMP4Handle, (MP4FileName)iTmpFileName.Ptr(), iFileCodecType);
       
   561         }
       
   562 
       
   563     if ( error == MP4_OUT_OF_MEMORY )
       
   564     	{
       
   565     	PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeOpen, error=%d"), error));
       
   566     	User::Leave(KErrNoMemory);
       
   567     	}
       
   568     else if (error != MP4_OK)
       
   569         {
       
   570         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeOpen, error=%d"), error));
       
   571         TInt64 currentdiskspace = DriveFreeSpaceL();
       
   572         iFileName = KNullDesC;
       
   573 
       
   574         if ( currentdiskspace < ((TInt64)KDiskSafetyLimit+iCriticalDiskVal+CurrentMetadataSize()) )
       
   575             {
       
   576             PRINT((_L("CCamC3GPDataSinkImp::OpenFileL disk full, available: %d"), I64INT(currentdiskspace)));
       
   577             iDiskFull = ETrue;
       
   578             User::Leave(KErrDiskFull);
       
   579             }
       
   580         else
       
   581             {
       
   582             PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Compose and Open failed, error=%d"), error));
       
   583             iFileName = KNullDesC;
       
   584             User::Leave(KErrGeneral);
       
   585             }
       
   586         }
       
   587     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Compose and Open done")));
       
   588 
       
   589     mp4_u32 composeFlags = 0;
       
   590     if ( aFileFormat == E3GPP2 )
       
   591         {
       
   592         composeFlags |= ( MP4_FLAG_METADATALAST | MP4_FLAG_LONGCLIP | MP4_FLAG_GENERATE_3G2);
       
   593         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Fileformat: 3G2")));
       
   594         }
       
   595     else if ( aFileFormat == EMPEG4 )
       
   596         {
       
   597         composeFlags |= ( MP4_FLAG_METADATALAST | MP4_FLAG_LONGCLIP | MP4_FLAG_GENERATE_MP4);
       
   598         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Fileformat: MP4")));
       
   599         }
       
   600     else // E3GPP
       
   601         {
       
   602         composeFlags |= ( MP4_FLAG_METADATALAST | MP4_FLAG_LONGCLIP );
       
   603         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Fileformat: 3GP")));
       
   604         }
       
   605 
       
   606     if ( ( iVideoMaxBitRate + iAudioAverageBitRate ) >= KLimitForLargeFileBuffers )
       
   607         {
       
   608         composeFlags |= MP4_FLAG_LARGEFILEBUFFER;
       
   609         }
       
   610 
       
   611     error = MP4ComposeSetFlags(iMP4Handle, composeFlags );
       
   612     if ( error == MP4_OUT_OF_MEMORY )
       
   613     	{
       
   614     	PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeSetFlags, error=%d"), error));
       
   615     	User::Leave(KErrNoMemory);
       
   616     	}
       
   617     else if (error != MP4_OK)
       
   618         {
       
   619         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeSetFlags, error=%d"), error));
       
   620         TInt64 currentdiskspace2 = DriveFreeSpaceL();
       
   621 
       
   622         if ( currentdiskspace2 < ((TInt64)KDiskSafetyLimit+iCriticalDiskVal+CurrentMetadataSize()) )
       
   623             {
       
   624             PRINT((_L("CCamC3GPDataSinkImp::OpenFileL disk full, available: %d"), I64INT(currentdiskspace2)));
       
   625             iDiskFull = ETrue;
       
   626             User::Leave(KErrDiskFull);
       
   627             }
       
   628         else
       
   629             {
       
   630             User::Leave(KErrGeneral);
       
   631             }
       
   632         }
       
   633     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Compose flags set")));
       
   634 
       
   635     if ((iFileCodecType & MP4_TYPE_H263_PROFILE_0) ||
       
   636         (iFileCodecType & MP4_TYPE_H263_PROFILE_3) ||
       
   637         (iFileCodecType & MP4_TYPE_MPEG4_VIDEO)    ||
       
   638         (iFileCodecType & MP4_TYPE_AVC_PROFILE_BASELINE) ||
       
   639         (iFileCodecType & MP4_TYPE_AVC_PROFILE_MAIN) ||
       
   640         (iFileCodecType & MP4_TYPE_AVC_PROFILE_HIGH))
       
   641         {
       
   642         // Set default values for video parameters if they are not set
       
   643         if (iVideoAverageBitRate < 0)
       
   644             {
       
   645             iVideoAverageBitRate = KVideoAverageBitRate;
       
   646             }
       
   647         if (iVideoMaxBitRate < 0)
       
   648             {
       
   649             iVideoMaxBitRate = KVideoMaxBitRate;
       
   650             }
       
   651         if (iVideoXResolution == 0)
       
   652             {
       
   653             iVideoXResolution = KVideoXResolution;
       
   654             }
       
   655         if (iVideoYResolution == 0)
       
   656             {
       
   657             iVideoYResolution = KVideoYResolution;
       
   658             }
       
   659 
       
   660         error = MP4ComposeAddVideoDescription(iMP4Handle,
       
   661                                               (mp4_u32)KVideoTimeScale,
       
   662                                               (mp4_u16)iVideoXResolution,
       
   663                                               (mp4_u16)iVideoYResolution,
       
   664                                               (mp4_u32)iVideoMaxBitRate,
       
   665                                               (mp4_u32)iVideoAverageBitRate);
       
   666 
       
   667         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeAddVideoDescription, error=%d"), error));
       
   668         if (error != MP4_OK)
       
   669             {
       
   670             User::Leave(KErrGeneral);
       
   671             }
       
   672         if ( (iFileCodecType & (MP4_TYPE_H263_PROFILE_0 | MP4_TYPE_H263_PROFILE_3))
       
   673             && ( videoLevel != 10) )
       
   674             {
       
   675             // H.263 level should be given to 3gp library like this
       
   676             error = MP4ComposeWriteVideoDecoderSpecificInfo(iMP4Handle,
       
   677                                                             (mp4_u8*)&videoLevel,
       
   678                                                             (mp4_u32)1);
       
   679             if ( error != MP4_OK )
       
   680                 {
       
   681                 PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeWriteVideoDecoderSpecificInfo, error=%d"), error));
       
   682                 User::Leave(KErrGeneral);
       
   683                 }
       
   684             }
       
   685         }
       
   686 
       
   687     if (iFileCodecType & MP4_TYPE_AMR_NB)
       
   688         {
       
   689         error = MP4ComposeAddAudioDescription(iMP4Handle,
       
   690                                               (mp4_u32)KAudioTimeScale,
       
   691                                               (mp4_u8)KAMRAudioFramesPerSample,
       
   692                                               (mp4_u16)KAudioModeSet);
       
   693         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeAddAudioDescription, AMR-NB error=%d"), error));
       
   694         if (error != MP4_OK)
       
   695             {
       
   696             User::Leave(KErrGeneral);
       
   697             }
       
   698         }
       
   699 
       
   700     if ( iFileCodecType & MP4_TYPE_MPEG4_AUDIO)
       
   701         {
       
   702         // To make sure we always write proper timescale to output file (even in case when we get no audio
       
   703         // buffers) the default samplerate is passed to 3GP library here.
       
   704         // When we get audio decoder specific information in WriteBuffer() the MP4ComposeAddAudioDescription()
       
   705         // will be called again with correct samplerate.
       
   706         error = MP4ComposeAddAudioDescription(iMP4Handle,
       
   707                                               (mp4_u32)KAACDefaultSampleRate,
       
   708                                               (mp4_u8)KAACAudioFramesPerSample,
       
   709                                               (mp4_u16)KAudioModeSet);
       
   710         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL MP4ComposeAddAudioDescription, AAC error=%d"), error));
       
   711         if (error != MP4_OK)
       
   712             {
       
   713             User::Leave(KErrGeneral);
       
   714             }
       
   715         }
       
   716 
       
   717     if ( iAvailableSpaceAtStart == 0 )
       
   718         {
       
   719         TVolumeInfo volumeinfo;
       
   720         User::LeaveIfError(iFS->Volume(volumeinfo, iDriveNumber));
       
   721         iAvailableSpaceAtStart = volumeinfo.iFree - (TInt64)(KDiskSafetyLimit+iCriticalDiskVal);
       
   722         }
       
   723 
       
   724     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Setting async file remover handler")));
       
   725     error = MP4ComposeSetTempFileRemoverObserver(&iMP4Handle, this);
       
   726     if (error != MP4_OK)
       
   727         {
       
   728         PRINT((_L("CCamC3GPDataSinkImp::OpenFileL Setting async file remover handler FAILED")));
       
   729         }
       
   730 
       
   731     PRINT((_L("CCamC3GPDataSinkImp::OpenFileL exit")));
       
   732     }
       
   733 
       
   734 
       
   735 // -----------------------------------------------------------------------------
       
   736 // CCamC3GPDataSinkImp::SetSizeLimit
       
   737 //
       
   738 // Set size limit of the 3GP file to be recorded in bytes. The limit must be
       
   739 // set before the recording starts.
       
   740 // -----------------------------------------------------------------------------
       
   741 //
       
   742 void CCamC3GPDataSinkImp::SetSizeLimit(TUint aSize)
       
   743     {
       
   744     PRINT((_L("CCamC3GPDataSinkImp::SetSizeLimit enter, requested limit: %u"), aSize));
       
   745     if (iBytesReceived)
       
   746         {
       
   747         PRINT(_L("CCamC3GPDataSinkImp::SetSizeLimit NOT set, recording"));
       
   748         return;
       
   749         }
       
   750 
       
   751     TInt64 rfileMaxSize = KCamC3GPMaximumFileSize; 
       
   752     if ( aSize == 0 || aSize > rfileMaxSize )
       
   753         {
       
   754         PRINT((_L("CCamC3GPDataSinkImp::SetSizeLimit 0 or over RFile max size, using internal max instead.")));
       
   755         iSizeLimit = rfileMaxSize; //max size for RFile
       
   756         }
       
   757     else
       
   758         {
       
   759         iSizeLimit = aSize;
       
   760         }
       
   761     PRINT((_L("CCamC3GPDataSinkImp::SetSizeLimit set to: high:%u low:%u"), I64HIGH(iSizeLimit), I64LOW(iSizeLimit)));
       
   762     }
       
   763 
       
   764 
       
   765 // -----------------------------------------------------------------------------
       
   766 // CCamC3GPDataSinkImp::GetElapsedTime
       
   767 //
       
   768 // Return the amount of time recording has been on in microseconds.
       
   769 // -----------------------------------------------------------------------------
       
   770 //
       
   771 TTimeIntervalMicroSeconds CCamC3GPDataSinkImp::GetElapsedTime()
       
   772     {
       
   773     PRINT(_L("CCamC3GPDataSinkImp::GetElapsedTime in"));
       
   774     TTimeIntervalMicroSeconds elapsed;
       
   775     if (iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0))
       
   776         {
       
   777         elapsed = 0;
       
   778         }
       
   779     else
       
   780         {
       
   781         elapsed = iVideoBufferTimestamp.Int64() - iFirstVideoFrameTimestamp.Int64();
       
   782         }
       
   783     PRINT((_L("CCamC3GPDataSinkImp::GetElapsedTime out, elapsed=%d"), I64INT(elapsed.Int64()) ));
       
   784     return elapsed;
       
   785     }
       
   786 
       
   787 
       
   788 // -----------------------------------------------------------------------------
       
   789 // CCamC3GPDataSinkImp::GetRemainingTime
       
   790 //
       
   791 // Return the estimated remaining time for the recording in microseconds.
       
   792 // This method takes into account the file size and disk full restrictions.
       
   793 // -----------------------------------------------------------------------------
       
   794 //
       
   795 TTimeIntervalMicroSeconds CCamC3GPDataSinkImp::GetRemainingTimeL()
       
   796     {
       
   797     TTimeIntervalMicroSeconds  elapsed;
       
   798     TTimeIntervalMicroSeconds  remaining;
       
   799     TTimeIntervalMicroSeconds  endtime;
       
   800     TInt64 availableSpace;
       
   801     TInt64 usedSpace;
       
   802     TInt64 metaDataSize;
       
   803     TBool remainingFromSizeLimit = EFalse;
       
   804 
       
   805     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL in")));
       
   806 
       
   807     if ( iAvailableSpaceAtStart == 0 )
       
   808         {
       
   809         TVolumeInfo volumeinfo;
       
   810         User::LeaveIfError(iFS->Volume(volumeinfo, iDriveNumber));
       
   811         iAvailableSpaceAtStart = volumeinfo.iFree - (TInt64)(KDiskSafetyLimit+iCriticalDiskVal);
       
   812         }
       
   813 
       
   814     if (iSizeLimit && ( iSizeLimit < iAvailableSpaceAtStart ) )
       
   815         {
       
   816         // use sizelimit as available space.
       
   817         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL Limiting remainingtime by sizelimit: %d."), I64INT(iSizeLimit)));
       
   818         remainingFromSizeLimit = ETrue;
       
   819         }
       
   820     else
       
   821         {
       
   822         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL Limiting remainingtime by available space at start: %d "), I64INT(iAvailableSpaceAtStart) ));
       
   823         }
       
   824 
       
   825     if ( iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0) )
       
   826         {
       
   827         elapsed = 0;
       
   828         }
       
   829     else
       
   830         {
       
   831         elapsed = iVideoBufferTimestamp.Int64() - iFirstVideoFrameTimestamp.Int64();
       
   832         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL elapsed with first=%d current=%d elapsed=%d"), I64INT(iFirstVideoFrameTimestamp.Int64()), I64INT(iVideoBufferTimestamp.Int64()), I64INT(elapsed.Int64()) ));
       
   833         }
       
   834 
       
   835     if (elapsed < (TTimeIntervalMicroSeconds)((TInt64)KDelayUseBitrates) )
       
   836         {
       
   837         // Use average audio/video bitrates to estimate remaining time
       
   838         TUint  averageBitRate;
       
   839         TUint  averageByteRate;
       
   840 
       
   841         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL: BitRates Video: %d , Audio: %d"), iVideoAverageBitRate, iAudioAverageBitRate ));
       
   842 
       
   843         averageBitRate = (TUint)((iVideoAverageBitRate + iAudioAverageBitRate) * KMetaDataCoeff);
       
   844         averageByteRate = averageBitRate / 8;
       
   845 
       
   846         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL: avaragebitrate: %d , avaragebyterate: %d"), averageBitRate, averageByteRate ));
       
   847 
       
   848         usedSpace = elapsed.Int64() * averageByteRate / 1000000; // 1000000 is for conversion between microseconds and seconds
       
   849 
       
   850         PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL: elapsed: %d, usedspace: %d"), I64INT(elapsed.Int64()), usedSpace ));
       
   851 
       
   852         metaDataSize = 2*CurrentMetadataSize();
       
   853         if (remainingFromSizeLimit)
       
   854             {
       
   855             availableSpace = iSizeLimit - usedSpace - metaDataSize;
       
   856             }
       
   857         else
       
   858             {
       
   859             availableSpace = iAvailableSpaceAtStart - usedSpace - metaDataSize;
       
   860             }
       
   861 
       
   862         if (availableSpace <= 0 || averageByteRate == 0)
       
   863             {
       
   864             remaining = 0;
       
   865             }
       
   866         else
       
   867             {
       
   868             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL: availablespace: %d, atStart: %d "), I64INT(elapsed.Int64()), I64INT(iAvailableSpaceAtStart) ));
       
   869 
       
   870             remaining = availableSpace * 1000000 / averageByteRate; // 1000000 is for conversion between microseconds and seconds
       
   871 
       
   872             if ( (remaining.Int64() + elapsed.Int64()) > (TInt64(KCamCMaxClipDurationInSecs)*1000000) )
       
   873                 {
       
   874                 remaining = (TInt64(KCamCMaxClipDurationInSecs)*1000000) - elapsed.Int64();
       
   875                 }
       
   876 
       
   877             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL: remaining: %d "), I64INT(remaining.Int64()) ));
       
   878             }
       
   879 
       
   880         // update also iAvarageEndTime to smooth jump at KDelayUseBitrates sec point.
       
   881         iAvarageEndTime = elapsed.Int64()+ remaining.Int64();
       
   882         }
       
   883     else // use real filesize estimates.
       
   884         {
       
   885         // used space is mediadata + 2x metadata (metadata in temp-files written and additionaö reserved space for stop copying it to output file.
       
   886         usedSpace = CurrentFileSize()+ 2*CurrentMetadataSize();
       
   887         if (remainingFromSizeLimit)
       
   888             {
       
   889             availableSpace = iSizeLimit - usedSpace;
       
   890             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL availableSpace from sizelimit: %d "), I64INT(iAvailableSpaceAtStart) ));
       
   891             }
       
   892         else
       
   893             {
       
   894             availableSpace = iAvailableSpaceAtStart - usedSpace;
       
   895             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL availableSpace from availablespaceAtStart: %d "), I64INT(iAvailableSpaceAtStart) ));
       
   896             }
       
   897 
       
   898         if (availableSpace <= 0)
       
   899             {
       
   900             remaining = 0;
       
   901             }
       
   902         else
       
   903             {
       
   904             // preserve integer precision by scaling the first dividend up in calculation
       
   905             if (remainingFromSizeLimit)
       
   906                 {
       
   907                 // divide the greater of iSizeLimit and elapsed with usedSpace first to prevent overflow
       
   908                 if ( iSizeLimit  > elapsed.Int64() )
       
   909                     {
       
   910                     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL iSizeLimit > elapsed: %d vs. %d"), I64INT(iSizeLimit), I64INT(elapsed.Int64()) ));
       
   911                     endtime = (((iSizeLimit * 1000) / usedSpace ) * elapsed.Int64() ) / 1000;
       
   912                     }
       
   913                 else
       
   914                     {
       
   915                     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL iSizeLimit < elapsed: %d vs. %d"), I64INT(iSizeLimit), I64INT(elapsed.Int64()) ));
       
   916                     endtime = ( iSizeLimit  * ( (elapsed.Int64() * 1000) / usedSpace )) / 1000;
       
   917                     }
       
   918                 }
       
   919             else
       
   920                 {
       
   921                 // divide the greater of iAvailableSpaceAtStart and elapsed with usedSpace first to prevent overflow
       
   922                 if (iAvailableSpaceAtStart > elapsed.Int64() )
       
   923                     {
       
   924                     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL iAvailableSpaceAtStart > elapsed: %d vs. %d"), I64INT(iAvailableSpaceAtStart), I64INT(elapsed.Int64()) ));
       
   925                     endtime = (( (iAvailableSpaceAtStart * 1000) / usedSpace ) * elapsed.Int64() ) / 1000;
       
   926                     }
       
   927                 else
       
   928                     {
       
   929                     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL iAvailableSpaceAtStart < elapsed: %d vs. %d"), I64INT(iAvailableSpaceAtStart), I64INT(elapsed.Int64()) ));
       
   930                     endtime = ( iAvailableSpaceAtStart * ( (elapsed.Int64() * 1000) / usedSpace )) / 1000;
       
   931                     }
       
   932                 }
       
   933 
       
   934             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL Endtime: %d"), I64INT(endtime.Int64()) ));
       
   935             if ( iAvarageEndTime.Int64() == -1 )
       
   936                 {
       
   937                 iAvarageEndTime = endtime;
       
   938                 }
       
   939             else
       
   940                 {
       
   941                 iAvarageEndTime = (( iAvarageEndTime.Int64() * 7 ) + endtime.Int64() ) / 8;
       
   942                 }
       
   943 
       
   944             if ( iAvarageEndTime.Int64() > (TInt64(KCamCMaxClipDurationInSecs)*1000000) )
       
   945                 {
       
   946                 iAvarageEndTime = (TInt64(KCamCMaxClipDurationInSecs)*1000000);
       
   947                 }
       
   948 
       
   949             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL elapsed: %d , usedspace: %d"), I64INT(elapsed.Int64()), I64INT(usedSpace) ));
       
   950             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL available: %d, atStart: %d"), I64INT(availableSpace), iAvailableSpaceAtStart));
       
   951             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL AvgEndtime: %d"), I64INT(iAvarageEndTime.Int64()) ));
       
   952             remaining = iAvarageEndTime.Int64() - elapsed.Int64();
       
   953             PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL remaining: %d"), I64INT(remaining.Int64()) ));
       
   954             }
       
   955         }
       
   956 
       
   957     // Check if remaining time has reached 0 and we need to stop right away
       
   958     if ( remaining <= TInt64(0) )
       
   959         {
       
   960         if ( elapsed >= TInt64(0) ) // we are recording.
       
   961             {
       
   962             if ( remainingFromSizeLimit || (elapsed >= (TInt64(KCamCMaxClipDurationInSecs)*1000000)) )
       
   963                 {
       
   964                 // Size limit has been set and we reach wanted size -> remaining time is 0
       
   965                 iFileSizeLimitReached = ETrue;
       
   966                 iObserver->MfcoSizeLimitReachedL();
       
   967                 }
       
   968             else
       
   969                 {
       
   970                 // Diskfull
       
   971                 iDiskFull = ETrue;
       
   972                 iObserver->MfcoDiskFullL();
       
   973                 }
       
   974             }
       
   975         remaining = 0;
       
   976         }
       
   977     PRINT((_L("CCamC3GPDataSinkImp::GetRemainingTimeL out")));
       
   978     return remaining;
       
   979     }
       
   980 
       
   981 
       
   982 // -----------------------------------------------------------------------------
       
   983 // CCamC3GPDataSinkImp::SinkStopL
       
   984 //
       
   985 // Order the sink to finalize and close the current 3GP file.
       
   986 // -----------------------------------------------------------------------------
       
   987 //
       
   988 void CCamC3GPDataSinkImp::SinkStopL()
       
   989     {
       
   990     MP4Err  error;
       
   991 
       
   992     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL enter")));
       
   993 
       
   994     if (!iMP4Handle)
       
   995         {
       
   996         return;
       
   997         }
       
   998 
       
   999     if (iVideoFrameDuration) // Write remaining video frame to disk
       
  1000         {
       
  1001         error = MP4ComposeWriteVideoFrame(iMP4Handle,
       
  1002                                           (mp4_u8 *)iVideoBuffer,
       
  1003                                           (mp4_u32)iVideoBufferFrameSize,
       
  1004                                           (mp4_u32)iVideoFrameDuration,
       
  1005                                           (mp4_bool)iVideoBufferRandomAccessPoint);
       
  1006         if (error != MP4_OK)
       
  1007             {
       
  1008             PRINT((_L("CCamC3GPDataSinkImp::SinkStopL MP4ComposeWriteVideoFrame, error=%d"), error));
       
  1009             User::Leave(KErrGeneral);
       
  1010             }
       
  1011         }
       
  1012 
       
  1013 
       
  1014     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL video frames written")));
       
  1015 
       
  1016 
       
  1017     if (iAudioFramesInBuffer) // Write remaining audio frames to disk
       
  1018         {
       
  1019         error = MP4ComposeWriteAudioFrames(iMP4Handle,
       
  1020                                            (mp4_u8 *)iAudioBuffer,
       
  1021                                            (mp4_u32)iAudioBufferFrameSize,
       
  1022                                            (mp4_u32)iAudioFramesInBuffer,
       
  1023                                            (mp4_u32)iAudioFramesInBuffer * KAudioFrameDuration);
       
  1024         if (error != MP4_OK)
       
  1025             {
       
  1026             PRINT((_L("CCamC3GPDataSinkImp::SinkStopL MP4ComposeWriteAudioFrames, error=%d"), error));
       
  1027             User::Leave(KErrGeneral);
       
  1028             }
       
  1029         }
       
  1030 
       
  1031     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL audio frames written")));
       
  1032 
       
  1033 
       
  1034     error = MP4ComposeClose(iMP4Handle);
       
  1035     iMP4Handle = NULL;
       
  1036     if (error != MP4_OK)
       
  1037         {
       
  1038         PRINT((_L("CCamC3GPDataSinkImp::SinkStopL MP4ComposeClose, error=%d"), error));
       
  1039         TInt64 currentdiskspace = DriveFreeSpaceL();
       
  1040 
       
  1041         if ( currentdiskspace < ((TInt64)KDiskSafetyLimit+iCriticalDiskVal+CurrentMetadataSize()) )
       
  1042             {
       
  1043             PRINT((_L("CCamC3GPDataSinkImp::SinkStopL disk full, available: %d"), I64INT(currentdiskspace)));
       
  1044             iDiskFull = ETrue;
       
  1045             User::Leave(KErrDiskFull);
       
  1046             }
       
  1047         else
       
  1048             {
       
  1049             User::Leave(KErrGeneral);
       
  1050             }
       
  1051         }
       
  1052 
       
  1053     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL file composed and closed")));
       
  1054 
       
  1055     if ( iFileHandleExists )
       
  1056         {
       
  1057         iMMFFile->SinkStopL();
       
  1058         iMMFFile = NULL; // not owned
       
  1059         }
       
  1060     else
       
  1061         {
       
  1062         if (!iBytesReceived)
       
  1063             {
       
  1064             PRINT((_L("CCamC3GPDataSinkImp::SinkStopL No data written, iTmpFileName left: '%s'"), iTmpFileName.Ptr()));
       
  1065             }
       
  1066         else
       
  1067             {
       
  1068             iFS->SetEntry(iTmpFileName, TTime(0), NULL, KEntryAttHidden);
       
  1069             PRINT((_L("CCamC3GPDataSinkImp::SinkStopL Renaming temp file to: '%s'"), iFileName.Ptr()));
       
  1070             User::LeaveIfError(iFS->Rename(iTmpFileName, iFileName));
       
  1071             }
       
  1072         }
       
  1073 
       
  1074     iFileName = KNullDesC;
       
  1075 
       
  1076     iBytesOfMetadata = 0;
       
  1077     iBufferSize = 0;
       
  1078     iFileCodecType = MP4_TYPE_NONE;
       
  1079     iVideoTimestamp = 0;
       
  1080     iVideoBufferTimestamp = -1;
       
  1081     iVideoRandomAccessPoint = EFalse;
       
  1082     iVideoBufferRandomAccessPoint = EFalse;
       
  1083     iVideoFrameDuration = 0;
       
  1084     iVideoBufferFrameSize = 0;
       
  1085     iVideoDecSpecInfoSize = 0;
       
  1086     iAudioDecSpecInfoSize = 0;
       
  1087     iAudioBufferFrameSize = 0;
       
  1088     iAudioFrameNumber = 0;
       
  1089     iAudioFramesInBuffer = 0;
       
  1090     iFileSizeLimitReached = EFalse;
       
  1091     iDiskFull = EFalse;
       
  1092     iFreeDiskSpace = 0;
       
  1093     iFreeDiskSpaceCounter = 0;
       
  1094     iAudioAACFrameDuration = 0;
       
  1095     iAudioAACSamplerate = 0;
       
  1096 
       
  1097     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL() updating available diskspace - in")));
       
  1098     TVolumeInfo volumeinfo;
       
  1099     if ( iFS && iFS->Volume(volumeinfo, iDriveNumber) == KErrNone )
       
  1100         {
       
  1101         iAvailableSpaceAtStart = volumeinfo.iFree - (TInt64)(KDiskSafetyLimit+iCriticalDiskVal);
       
  1102         PRINT((_L("CCamC3GPDataSinkImp::SinkStopL() updating available diskspace - done")));
       
  1103         }
       
  1104 
       
  1105     PRINT((_L("CCamC3GPDataSinkImp::SinkStopL exit")));
       
  1106     }
       
  1107 
       
  1108 
       
  1109 // -----------------------------------------------------------------------------
       
  1110 // CCamC3GPDataSinkImp::WriteBuffer
       
  1111 //
       
  1112 // Write an audio/video buffer to the sink. The sink copies the given buffer
       
  1113 // and writes it to the file.
       
  1114 // -----------------------------------------------------------------------------
       
  1115 //
       
  1116 void CCamC3GPDataSinkImp::WriteBufferL(CCMRMediaBuffer* aBuffer)
       
  1117     {
       
  1118     PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL enter")));
       
  1119     TInt64  videoduration = 0;
       
  1120     TUint8* tmpaudiobuffer = 0;
       
  1121     TInt64 currentfilesize;
       
  1122     MP4Err  error = MP4_OK;
       
  1123 
       
  1124 
       
  1125     if (!iMP4Handle)
       
  1126         {
       
  1127         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL No MP4Handle, returning.")));
       
  1128         return;
       
  1129         }
       
  1130 
       
  1131     if (iFileSizeLimitReached || iDiskFull)
       
  1132         {
       
  1133         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL sizelimit reached or disk full returning")));
       
  1134         return;
       
  1135         }
       
  1136 
       
  1137     iBufferType = aBuffer->Type();
       
  1138     iBufferSize = aBuffer->BufferSize();
       
  1139 
       
  1140     TTimeIntervalMicroSeconds elapsed;
       
  1141     if (iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0))
       
  1142         {
       
  1143         elapsed = 0;
       
  1144         }
       
  1145     else
       
  1146         {
       
  1147         elapsed = iVideoBufferTimestamp.Int64() - iFirstVideoFrameTimestamp.Int64();
       
  1148         }
       
  1149 
       
  1150     currentfilesize = CurrentFileSize() + CurrentMetadataSize();
       
  1151     if ( ( iSizeLimit && ((currentfilesize + (TUint)iBufferSize) > iSizeLimit) ) ||
       
  1152          (elapsed.Int64() >= (TInt64(KCamCMaxClipDurationInSecs)*1000000)) )
       
  1153         {
       
  1154         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL sizelimit reached, filesize: %d"), I64INT(currentfilesize)));
       
  1155         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL sizelimit is set to: high:%u low:%u"), I64HIGH(iSizeLimit), I64LOW(iSizeLimit)));
       
  1156         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL elapsed time: high:%u low:%u"), I64HIGH(elapsed.Int64()), I64LOW(elapsed.Int64())));        
       
  1157         iFileSizeLimitReached = ETrue;
       
  1158         iObserver->MfcoSizeLimitReachedL();
       
  1159         return;
       
  1160         }
       
  1161 
       
  1162     PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL, filesize: %d, bufsize: %d")
       
  1163             , I64INT(currentfilesize), iBufferSize));
       
  1164 
       
  1165     currentfilesize += CurrentMetadataSize(); // extra reserve for stop (copy metadata from temp files to end of output file.
       
  1166     if ( currentfilesize >= iAvailableSpaceAtStart )
       
  1167         {
       
  1168         PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL disk full, calc size: %d"), I64INT(currentfilesize)));
       
  1169         iDiskFull = ETrue;
       
  1170         iObserver->MfcoDiskFullL();
       
  1171         return;
       
  1172         }
       
  1173 
       
  1174     PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL, available: %d")
       
  1175             , I64INT(iAvailableSpaceAtStart-currentfilesize)));
       
  1176 
       
  1177     iBytesReceived += (TUint)iBufferSize;
       
  1178     switch (iBufferType)
       
  1179         {
       
  1180         case CCMRMediaBuffer::EAudioAMRNB:
       
  1181             {
       
  1182             iAudioFrameNumber++;
       
  1183 
       
  1184             if ( ( (TUint)iBufferSize + iAudioBufferFrameSize ) > iAudioBufferSize) // Incoming buffer doesn't fit into allocated buffer
       
  1185                 {
       
  1186                 tmpaudiobuffer = new (ELeave) TUint8[(TUint)iBufferSize + iAudioBufferFrameSize];
       
  1187                 Mem::Copy(tmpaudiobuffer, iAudioBuffer, (TInt)iAudioBufferFrameSize);
       
  1188                 delete [] iAudioBuffer;
       
  1189                 iAudioBuffer = tmpaudiobuffer;
       
  1190                 iAudioBufferSize = (TUint)iBufferSize + iAudioBufferFrameSize;
       
  1191                 }
       
  1192 
       
  1193             Mem::Copy(iAudioBuffer + iAudioBufferFrameSize, aBuffer->Data().Ptr(), iBufferSize);
       
  1194             iAudioBufferFrameSize += (TUint)iBufferSize;
       
  1195             iAudioFramesInBuffer++;
       
  1196 
       
  1197             if (iAudioFramesInBuffer == KAMRAudioFramesPerSample) // Buffer several audio frames before writing to disk
       
  1198                 {
       
  1199                 error = MP4ComposeWriteAudioFrames(iMP4Handle,
       
  1200                                                    (mp4_u8 *)iAudioBuffer,
       
  1201                                                    (mp4_u32)iAudioBufferFrameSize,
       
  1202                                                    (mp4_u32)iAudioFramesInBuffer,
       
  1203                                                    (mp4_u32)iAudioFramesInBuffer * KAudioFrameDuration);
       
  1204                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL AMR-NB MP4ComposeWriteAudioFrames, error=%d"), error));
       
  1205                 if (error != MP4_OK)
       
  1206                     {
       
  1207                     User::Leave(KErrGeneral);
       
  1208                     }
       
  1209 
       
  1210                 iAudioFramesInBuffer = 0;
       
  1211                 iAudioBufferFrameSize = 0;
       
  1212                 }
       
  1213 
       
  1214             break;
       
  1215             }
       
  1216         case CCMRMediaBuffer::EAudioMPEG4AAC:
       
  1217             {
       
  1218             if ( !iAudioAACFrameDuration )
       
  1219                 {
       
  1220                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL AAC Audio frameduration not set! Error= -18"), error));
       
  1221                 User::Leave ( KErrNotReady );
       
  1222                 }
       
  1223 
       
  1224             iAudioFrameNumber++;
       
  1225             error = MP4ComposeWriteAudioFrames(iMP4Handle,
       
  1226                                                (mp4_u8 *)aBuffer->Data().Ptr(),
       
  1227                                                (mp4_u32)aBuffer->BufferSize(),
       
  1228                                                (mp4_u32)KAACAudioFramesPerSample,
       
  1229                                                (mp4_u32)KAACAudioFramesPerSample * iAudioAACFrameDuration);
       
  1230             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL AAC MP4ComposeWriteAudioFrames, error=%d"), error));
       
  1231             if (error != MP4_OK)
       
  1232                 {
       
  1233                 User::Leave(KErrGeneral);
       
  1234                 }
       
  1235             break;
       
  1236             }
       
  1237         case CCMRMediaBuffer::EAudioAMRWB:
       
  1238             {
       
  1239             break;
       
  1240             }
       
  1241         case CCMRMediaBuffer::EVideoH263:
       
  1242         case CCMRMediaBuffer::EVideoMPEG4:
       
  1243             {
       
  1244             iVideoTimestamp = aBuffer->TimeStamp();
       
  1245             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL EVideoH263/EVideoMPEG4 Timestamp of the buffer is %d"), I64INT(iVideoTimestamp.Int64())));
       
  1246             iVideoRandomAccessPoint = aBuffer->RandomAccessPoint();
       
  1247             iVideoFrameNumber++;
       
  1248             if (iVideoRandomAccessPoint)
       
  1249                 {
       
  1250                 iVideoIntraFrameNumber++;
       
  1251                 }
       
  1252 
       
  1253             if (iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0)) // First frame
       
  1254                 {
       
  1255                 iFirstVideoFrameTimestamp = iVideoTimestamp;
       
  1256                 iVideoBufferTimestamp = iVideoTimestamp;
       
  1257                 iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1258 
       
  1259                 if ((TUint)iBufferSize > iVideoBufferSize)
       
  1260                     {
       
  1261                     delete [] iVideoBuffer;
       
  1262                     iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1263                     iVideoBufferSize = (TUint)iBufferSize;
       
  1264                     }
       
  1265 
       
  1266                 Mem::Copy(iVideoBuffer, aBuffer->Data().Ptr(), iBufferSize);
       
  1267                 iVideoBufferFrameSize = (TUint)iBufferSize;
       
  1268 
       
  1269                 break;
       
  1270                 }
       
  1271 
       
  1272             videoduration = iVideoTimestamp.Int64() - iVideoBufferTimestamp.Int64(); // Duration in microseconds
       
  1273             videoduration = TInt64((videoduration * KVideoTimeScale) / 1E6 + 0.5); // Duration scaled to KVideoTimeScale
       
  1274             iVideoFrameDuration = (TUint)I64INT(videoduration);
       
  1275 
       
  1276             error = MP4ComposeWriteVideoFrame(iMP4Handle,
       
  1277                                               (mp4_u8 *)iVideoBuffer,
       
  1278                                               (mp4_u32)iVideoBufferFrameSize,
       
  1279                                               (mp4_u32)iVideoFrameDuration,
       
  1280                                               (mp4_bool)iVideoBufferRandomAccessPoint);
       
  1281             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoFrame, error=%d"), error));
       
  1282             if (error != MP4_OK)
       
  1283                 {
       
  1284                 User::Leave(KErrGeneral);
       
  1285                 }
       
  1286 
       
  1287             if ((TUint)iBufferSize > iVideoBufferSize)
       
  1288                 {
       
  1289                 delete [] iVideoBuffer;
       
  1290                 iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1291                 iVideoBufferSize = (TUint)iBufferSize;
       
  1292                 }
       
  1293 
       
  1294             Mem::Copy(iVideoBuffer, aBuffer->Data().Ptr(), iBufferSize);
       
  1295             iVideoBufferFrameSize = (TUint)iBufferSize;
       
  1296             iVideoBufferTimestamp = iVideoTimestamp;
       
  1297             iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1298 
       
  1299             break;
       
  1300             }
       
  1301         case CCMRMediaBuffer::EVideoMPEG4DecSpecInfo:
       
  1302             {
       
  1303             iVideoDecSpecInfoSize = iBufferSize;
       
  1304 
       
  1305             error = MP4ComposeWriteVideoDecoderSpecificInfo(iMP4Handle,
       
  1306                                                             (mp4_u8 *)aBuffer->Data().Ptr(),
       
  1307                                                             (mp4_u32)iBufferSize);
       
  1308             if (error != MP4_OK)
       
  1309                 {
       
  1310                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoDecoderSpecificInfo, error=%d"), error));
       
  1311                 User::Leave(KErrGeneral);
       
  1312                 }
       
  1313 
       
  1314             break;
       
  1315             }
       
  1316         case CCMRMediaBuffer::EVideoH264NAL:
       
  1317             {
       
  1318             iVideoTimestamp = aBuffer->TimeStamp();
       
  1319             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL EVideoH264NAL Timestamp of the buffer is %d"), I64INT(iVideoTimestamp.Int64())));
       
  1320             iVideoRandomAccessPoint = aBuffer->RandomAccessPoint();
       
  1321             iVideoFrameNumber++;
       
  1322             if (iVideoRandomAccessPoint)
       
  1323                 {
       
  1324                 iVideoIntraFrameNumber++;
       
  1325                 }
       
  1326 
       
  1327             if (iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0)) // First frame
       
  1328                 {
       
  1329                 iFirstVideoFrameTimestamp = iVideoTimestamp;
       
  1330                 iVideoBufferTimestamp = iVideoTimestamp;
       
  1331                 iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1332 
       
  1333                 if ((TUint)(iBufferSize) > iVideoBufferSize)
       
  1334                     {
       
  1335                     delete [] iVideoBuffer;
       
  1336                     iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1337                     iVideoBufferSize = (TUint)iBufferSize;
       
  1338                     }
       
  1339 
       
  1340                 ConvertNALEncapsulationToNALSizes( aBuffer );
       
  1341                 break;
       
  1342                 }
       
  1343 
       
  1344             videoduration = iVideoTimestamp.Int64() - iVideoBufferTimestamp.Int64(); // Duration in microseconds
       
  1345             videoduration = TInt64((videoduration * KVideoTimeScale) / 1E6 + 0.5); // Duration scaled to KVideoTimeScale
       
  1346             iVideoFrameDuration = (TUint)I64INT(videoduration);
       
  1347 
       
  1348             error = MP4ComposeWriteVideoFrame(iMP4Handle,
       
  1349                                               (mp4_u8 *)iVideoBuffer,
       
  1350                                               (mp4_u32)iVideoBufferFrameSize,
       
  1351                                               (mp4_u32)iVideoFrameDuration,
       
  1352                                               (mp4_bool)iVideoBufferRandomAccessPoint);
       
  1353             if (error != MP4_OK)
       
  1354                 {
       
  1355                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoFrame, error=%d"), error));
       
  1356                 User::Leave(KErrGeneral);
       
  1357                 }
       
  1358 
       
  1359             if ((TUint)(iBufferSize) > iVideoBufferSize)
       
  1360                 {
       
  1361                 delete [] iVideoBuffer;
       
  1362                 iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1363                 iVideoBufferSize = (TUint)iBufferSize;
       
  1364                 }
       
  1365 
       
  1366             ConvertNALEncapsulationToNALSizes( aBuffer );
       
  1367 
       
  1368             iVideoBufferTimestamp = iVideoTimestamp;
       
  1369             iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1370             break;
       
  1371             }
       
  1372         case CCMRMediaBuffer::EVideoH264Bytestream:
       
  1373             {
       
  1374             // need to add NAL header to end on bytestream buffer
       
  1375             iVideoTimestamp = aBuffer->TimeStamp();
       
  1376             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL EVideoH264Bytestream Timestamp of the buffer is %d"), I64INT(iVideoTimestamp.Int64())));
       
  1377             iVideoRandomAccessPoint = aBuffer->RandomAccessPoint();
       
  1378             iVideoFrameNumber++;
       
  1379             if (iVideoRandomAccessPoint)
       
  1380                 {
       
  1381                 iVideoIntraFrameNumber++;
       
  1382                 }
       
  1383 
       
  1384             if (iVideoBufferTimestamp < TTimeIntervalMicroSeconds(0)) // First frame
       
  1385                 {
       
  1386                 iFirstVideoFrameTimestamp = iVideoTimestamp;
       
  1387                 iVideoBufferTimestamp = iVideoTimestamp;
       
  1388                 iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1389 
       
  1390                 if ((TUint)(iBufferSize) > iVideoBufferSize)
       
  1391                     {
       
  1392                     delete [] iVideoBuffer;
       
  1393                     iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1394                     iVideoBufferSize = (TUint)iBufferSize;
       
  1395                     }
       
  1396 
       
  1397                 ConvertBytestreamHeadersToNALSizes(aBuffer);
       
  1398                 Mem::Copy(iVideoBuffer, aBuffer->Data().Ptr(), iBufferSize);
       
  1399                 iVideoBufferFrameSize = iBufferSize;
       
  1400                 break;
       
  1401                 }
       
  1402 
       
  1403             videoduration = iVideoTimestamp.Int64() - iVideoBufferTimestamp.Int64(); // Duration in microseconds
       
  1404             videoduration = TInt64((videoduration * KVideoTimeScale) / 1E6 + 0.5); // Duration scaled to KVideoTimeScale
       
  1405             iVideoFrameDuration = (TUint)I64INT(videoduration);
       
  1406 
       
  1407             error = MP4ComposeWriteVideoFrame(iMP4Handle,
       
  1408                                               (mp4_u8 *)iVideoBuffer,
       
  1409                                               (mp4_u32)iVideoBufferFrameSize,
       
  1410                                               (mp4_u32)iVideoFrameDuration,
       
  1411                                               (mp4_bool)iVideoBufferRandomAccessPoint);
       
  1412             if (error != MP4_OK)
       
  1413                 {
       
  1414                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoFrame, error=%d"), error));
       
  1415                 User::Leave(KErrGeneral);
       
  1416                 }
       
  1417 
       
  1418             if ((TUint)(iBufferSize) > iVideoBufferSize)
       
  1419                 {
       
  1420                 delete [] iVideoBuffer;
       
  1421                 iVideoBuffer = new (ELeave) TUint8[(TUint)iBufferSize];
       
  1422                 iVideoBufferSize = (TUint)iBufferSize;
       
  1423                 }
       
  1424 
       
  1425             ConvertBytestreamHeadersToNALSizes(aBuffer);
       
  1426             Mem::Copy(iVideoBuffer, aBuffer->Data().Ptr(), iBufferSize);
       
  1427 
       
  1428             iVideoBufferFrameSize = (TUint)iBufferSize;
       
  1429             iVideoBufferTimestamp = iVideoTimestamp;
       
  1430             iVideoBufferRandomAccessPoint = iVideoRandomAccessPoint;
       
  1431             break;
       
  1432             }
       
  1433         case CCMRMediaBuffer::EVideoH264NALDecSpecInfo:
       
  1434             {
       
  1435             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL EVideoH264NALDecSpecInfo")));            
       
  1436             HBufC8* outputAVCHeader = 0;
       
  1437             outputAVCHeader = (HBufC8*) HBufC8::NewLC(16384);
       
  1438             TPtr8 destptr = outputAVCHeader->Des();
       
  1439 
       
  1440 	        // parse header & convert it to AVCDecoderConfigurationRecord -format
       
  1441 	        ConvertAVCHeaderNALL(aBuffer, destptr);
       
  1442             iVideoDecSpecInfoSize = destptr.Length();
       
  1443 
       
  1444             error = MP4ComposeWriteVideoDecoderSpecificInfo(iMP4Handle,
       
  1445                                                             (mp4_u8 *)destptr.Ptr(),
       
  1446                                                             (mp4_u32)iVideoDecSpecInfoSize);
       
  1447 
       
  1448 			CleanupStack::PopAndDestroy( outputAVCHeader );
       
  1449             if (error != MP4_OK)
       
  1450                 {
       
  1451                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoDecoderSpecificInfo, error=%d"), error));
       
  1452                 User::Leave(KErrGeneral);
       
  1453                 }
       
  1454             break;
       
  1455             }
       
  1456         case CCMRMediaBuffer::EVideoH264BytestreamDecSpecInfo:
       
  1457             {
       
  1458             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL EVideoH264BytestreamDecSpecInfo")));            
       
  1459             HBufC8* outputAVCHeader = 0;
       
  1460             outputAVCHeader = (HBufC8*) HBufC8::NewLC(16384);
       
  1461             TPtr8 destptr = outputAVCHeader->Des();
       
  1462 
       
  1463 	        // parse header & convert it to AVCDecoderConfigurationRecord -format
       
  1464 	        ConvertAVCHeaderByteStreamL(aBuffer, destptr);
       
  1465             iVideoDecSpecInfoSize = destptr.Length();
       
  1466 
       
  1467             error = MP4ComposeWriteVideoDecoderSpecificInfo(iMP4Handle,
       
  1468                                                             (mp4_u8 *)destptr.Ptr(),
       
  1469                                                             (mp4_u32)iVideoDecSpecInfoSize);
       
  1470 
       
  1471 			CleanupStack::PopAndDestroy( outputAVCHeader );
       
  1472             if (error != MP4_OK)
       
  1473                 {
       
  1474                 PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteVideoDecoderSpecificInfo, error=%d"), error));
       
  1475                 User::Leave(KErrGeneral);
       
  1476                 }
       
  1477             break;
       
  1478             }
       
  1479         case CCMRMediaBuffer::EAudioDecSpecInfo:
       
  1480             {
       
  1481 			PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteAudioDecoderSpecificInfo in"), error));
       
  1482             iAudioDecSpecInfoSize = iBufferSize;
       
  1483 
       
  1484             error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle,
       
  1485                                                             (mp4_u8 *)aBuffer->Data().Ptr(),
       
  1486                                                             (mp4_u32)iBufferSize);
       
  1487             PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteAudioDecoderSpecificInfo, error=%d"), error));
       
  1488             if (error != MP4_OK)
       
  1489                 {
       
  1490                 User::Leave(KErrGeneral);
       
  1491                 }
       
  1492 
       
  1493 			PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteAudioDecoderSpecificInfo - flags: iFileCodecType=%d Frameduration=%d"), iFileCodecType, iAudioAACFrameDuration));
       
  1494             if ( (iFileCodecType & MP4_TYPE_MPEG4_AUDIO) && !iAudioAACFrameDuration )
       
  1495                 {
       
  1496 				PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteAudioDecoderSpecificInfo determining new AAC samplerate."), error));
       
  1497                 DetermineAACFrameDurationL( aBuffer );
       
  1498                 // done here because timescale is dependent of samplerate.
       
  1499                 error = MP4ComposeAddAudioDescription(iMP4Handle,
       
  1500                                                      (mp4_u32)iAudioAACSamplerate,
       
  1501                                                      (mp4_u8)KAACAudioFramesPerSample,
       
  1502                                                      (mp4_u16)KAudioModeSet);
       
  1503                 if (error != MP4_OK)
       
  1504                     {
       
  1505                     PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeAddAudioDescription, error=%d"), error));
       
  1506                     User::Leave(KErrGeneral);
       
  1507                     }
       
  1508                 }
       
  1509 			PRINT((_L("CCamC3GPDataSinkImp::WriteBufferL MP4ComposeWriteAudioDecoderSpecificInfo out"), error));
       
  1510             break;
       
  1511             }
       
  1512         default:
       
  1513             {
       
  1514             break;
       
  1515             }
       
  1516         }
       
  1517     }
       
  1518 
       
  1519 
       
  1520 // -----------------------------------------------------------------------------
       
  1521 // CCamC3GPDataSinkImp::SetVideoFrameSize
       
  1522 //
       
  1523 // Give video frame size to sink.
       
  1524 // -----------------------------------------------------------------------------
       
  1525 //
       
  1526 TInt CCamC3GPDataSinkImp::SetVideoFrameSize(TSize aSize)
       
  1527     {
       
  1528     if (aSize.iWidth < 0)
       
  1529         {
       
  1530         return KErrArgument;
       
  1531         }
       
  1532     if (aSize.iHeight < 0)
       
  1533         {
       
  1534         return KErrArgument;
       
  1535         }
       
  1536 
       
  1537     if (iBytesReceived)
       
  1538         {
       
  1539         return KErrNotReady;
       
  1540         }
       
  1541 
       
  1542     iVideoXResolution = aSize.iWidth;
       
  1543     iVideoYResolution = aSize.iHeight;
       
  1544     return KErrNone;
       
  1545     }
       
  1546 
       
  1547 
       
  1548 // -----------------------------------------------------------------------------
       
  1549 // CCamC3GPDataSinkImp::SetAverageVideoBitRate
       
  1550 //
       
  1551 // Give average video bitrate to sink.
       
  1552 // -----------------------------------------------------------------------------
       
  1553 //
       
  1554 TInt CCamC3GPDataSinkImp::SetAverageVideoBitRate(TInt aBitRate)
       
  1555     {
       
  1556     if (aBitRate < 0)
       
  1557         {
       
  1558         return KErrArgument;
       
  1559         }
       
  1560 
       
  1561     iVideoAverageBitRate = aBitRate;
       
  1562     return KErrNone;
       
  1563     }
       
  1564 
       
  1565 
       
  1566 // -----------------------------------------------------------------------------
       
  1567 // CCamC3GPDataSinkImp::SetMaxVideoBitRate
       
  1568 //
       
  1569 // Give maximum video bitrate to sink.
       
  1570 // -----------------------------------------------------------------------------
       
  1571 //
       
  1572 TInt CCamC3GPDataSinkImp::SetMaxVideoBitRate(TInt aBitRate)
       
  1573     {
       
  1574     if (aBitRate < 0)
       
  1575         {
       
  1576         return KErrArgument;
       
  1577         }
       
  1578 
       
  1579     iVideoMaxBitRate = aBitRate;
       
  1580     return KErrNone;
       
  1581     }
       
  1582 
       
  1583 
       
  1584 // -----------------------------------------------------------------------------
       
  1585 // CCamC3GPDataSinkImp::SetAverageAudioBitRate
       
  1586 //
       
  1587 // Give average audio bitrate to sink.
       
  1588 // -----------------------------------------------------------------------------
       
  1589 //
       
  1590 TInt CCamC3GPDataSinkImp::SetAverageAudioBitRate(TInt aBitRate)
       
  1591     {
       
  1592     if (aBitRate < 0)
       
  1593         {
       
  1594         return KErrArgument;
       
  1595         }
       
  1596 
       
  1597     iAudioAverageBitRate = aBitRate;
       
  1598     return KErrNone;
       
  1599     }
       
  1600 
       
  1601 
       
  1602 // -----------------------------------------------------------------------------
       
  1603 // CCamC3GPDataSinkImp::CurrentFileSize
       
  1604 //
       
  1605 // Estimate current output file size.
       
  1606 // Total file size = metadata size + media data size
       
  1607 // -----------------------------------------------------------------------------
       
  1608 //
       
  1609 TUint CCamC3GPDataSinkImp::CurrentFileSize() const
       
  1610     {
       
  1611     TUint filesize = 0;
       
  1612 
       
  1613     // Media data
       
  1614     filesize += 8; // mdat box type and size
       
  1615     filesize += iBytesReceived; // Data received from media recorder
       
  1616 
       
  1617     return filesize;
       
  1618     }
       
  1619 
       
  1620 
       
  1621 // -----------------------------------------------------------------------------
       
  1622 // CCamC3GPDataSinkImp::CurrentMetadataSize
       
  1623 //
       
  1624 // Calculates current metadata size.
       
  1625 // -----------------------------------------------------------------------------
       
  1626 //
       
  1627 TUint CCamC3GPDataSinkImp::CurrentMetadataSize() const
       
  1628     {
       
  1629     TBool haveAudio;
       
  1630     TBool haveVideo;
       
  1631     TUint metadatasize = 0;
       
  1632 
       
  1633     haveAudio = EFalse;
       
  1634     haveVideo = EFalse;
       
  1635 
       
  1636 
       
  1637     // Metadata
       
  1638 
       
  1639     metadatasize += KFTYPSize; // FTYP
       
  1640 
       
  1641     if ((iFileCodecType & MP4_TYPE_H263_PROFILE_0) ||
       
  1642         (iFileCodecType & MP4_TYPE_H263_PROFILE_3)) // H.263
       
  1643         {
       
  1644         haveVideo = ETrue;
       
  1645         metadatasize += 574; // Constant size H.263 metadata
       
  1646         metadatasize += (iVideoFrameNumber * 16 + iVideoIntraFrameNumber * 4); // Content dependent H.263 metadata
       
  1647         }
       
  1648 
       
  1649     if (iFileCodecType & MP4_TYPE_MPEG4_VIDEO) // MPEG-4 video
       
  1650         {
       
  1651         haveVideo = ETrue;
       
  1652         metadatasize += 596; // Constant size MPEG-4 video metadata
       
  1653         metadatasize += (iVideoFrameNumber * 16 + iVideoIntraFrameNumber * 4 + (TUint)iVideoDecSpecInfoSize); // Content dependent MPEG-4 video metadata
       
  1654         }
       
  1655 
       
  1656     if ( iFileCodecType & MP4_TYPE_AMR_NB ) // AMR-NB
       
  1657         {
       
  1658         haveAudio = ETrue;
       
  1659         metadatasize += 514; // Constant size AMR metadata
       
  1660         metadatasize += ((iAudioFrameNumber + KAMRAudioFramesPerSample - 1) / KAMRAudioFramesPerSample) * 16;
       
  1661         }
       
  1662 
       
  1663     if ( iFileCodecType & MP4_TYPE_MPEG4_AUDIO ) // MPEG-4 AAC-LC
       
  1664         {
       
  1665         haveAudio = ETrue;
       
  1666         metadatasize += 514; // Constant size metadata
       
  1667         metadatasize += (iAudioFrameNumber * 16) + (TUint)iAudioDecSpecInfoSize;
       
  1668         }
       
  1669 
       
  1670     if (haveAudio && haveVideo)
       
  1671         metadatasize -= 116; // There is only one moov and mvhd in a file
       
  1672 
       
  1673     return metadatasize;
       
  1674     }
       
  1675 
       
  1676 
       
  1677 // -----------------------------------------------------------------------------
       
  1678 // CCamC3GPDataSinkImp::DriveFreeSpaceL
       
  1679 //
       
  1680 // Calculate free space on a drive in bytes.
       
  1681 // -----------------------------------------------------------------------------
       
  1682 //
       
  1683 TInt64 CCamC3GPDataSinkImp::DriveFreeSpaceL()
       
  1684     {
       
  1685     TVolumeInfo volumeinfo;
       
  1686 
       
  1687     if (iFreeDiskSpaceCounter % KFreeDiskSpaceCounter == 0)
       
  1688         {
       
  1689         PRINT((_L("CCamC3GPDataSinkImp::DriveFreeSpaceL Asking Disk Free space")));
       
  1690         User::LeaveIfError(iFS->Volume(volumeinfo, iDriveNumber));
       
  1691         iFreeDiskSpace = volumeinfo.iFree;
       
  1692         PRINT((_L("CCamC3GPDataSinkImp::DriveFreeSpaceL Received Disk Free space info")));
       
  1693         }
       
  1694 
       
  1695     iFreeDiskSpaceCounter++;
       
  1696     return iFreeDiskSpace;
       
  1697     }
       
  1698 
       
  1699 
       
  1700 // -----------------------------------------------------------------------------
       
  1701 // CCamC3GPDataSinkImp::DetermineAACFrameDuration
       
  1702 //
       
  1703 // Determines AAC audio frame duration.
       
  1704 // -----------------------------------------------------------------------------
       
  1705 //
       
  1706 void CCamC3GPDataSinkImp::DetermineAACFrameDurationL( CCMRMediaBuffer* aBuffer )
       
  1707     {
       
  1708     TInt sampleRate = 0;
       
  1709     TUint8 sampleRateIndex = *aBuffer->Data().Mid(0).Ptr();
       
  1710     sampleRateIndex <<= 5;
       
  1711     sampleRateIndex >>= 4;
       
  1712     sampleRateIndex |= ((TUint8)*aBuffer->Data().Mid(1).Ptr())>>7;
       
  1713 
       
  1714     switch ( sampleRateIndex )
       
  1715         {
       
  1716         case 0x3:
       
  1717             {
       
  1718             PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset to 48000")));
       
  1719             sampleRate = 48000;
       
  1720             break;
       
  1721             }
       
  1722         case 0x5:
       
  1723             {
       
  1724 			PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset to 32000")));
       
  1725             sampleRate = 32000;
       
  1726             break;
       
  1727             }
       
  1728         case 0x6:
       
  1729             {
       
  1730             PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset to 24000")));
       
  1731             sampleRate = 24000;
       
  1732             break;
       
  1733             }
       
  1734         case 0x8:
       
  1735             {
       
  1736             PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset to 16000")));
       
  1737             sampleRate = 16000;
       
  1738             break;
       
  1739             }
       
  1740         case 0xb:
       
  1741             {
       
  1742             PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset to 8000")));
       
  1743             sampleRate = 8000;
       
  1744             break;
       
  1745             }
       
  1746         default:
       
  1747             {
       
  1748             PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL unsupported AAC Samplerate - leaving -6")));
       
  1749             User::Leave( KErrArgument );
       
  1750             break;
       
  1751             }
       
  1752         }
       
  1753 
       
  1754     PRINT((_L("CCamC3GPDataSinkImp::DetermineAACFrameDurationL AAC Samplerate reset from %d to %d"), iAudioAACSamplerate, sampleRate));
       
  1755     iAudioAACSamplerate = sampleRate;
       
  1756     // formula to calculate frameduration from samplerate is: frameduration = (1024/samplerate)*1000
       
  1757     // and in movie timescale: frameDurationInMovieTimescale = frameduration*samplerate/1000
       
  1758     // thus with equal samplerate = timescale frameDurationInMovieTimescale for AAC is always 1024
       
  1759     iAudioAACFrameDuration = 1024;
       
  1760 }
       
  1761 
       
  1762 // -----------------------------------------------------------------------------
       
  1763 // CCamC3GPDataSinkImp::ConvertAVCHeaderL
       
  1764 //
       
  1765 // Convert AVC specific decoder config info to
       
  1766 // AVC Decoder Configuration Record -format
       
  1767 // -----------------------------------------------------------------------------
       
  1768 //
       
  1769 void CCamC3GPDataSinkImp::ConvertAVCHeaderNALL( CCMRMediaBuffer* aBuffer, TDes8& aDstBuf )
       
  1770     {
       
  1771     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL in Buffer length: %d"), aBuffer->Data().Length() ));    
       
  1772 	TUint8* inputPtr = (TUint8*)(aBuffer->Data().Ptr());
       
  1773     TUint8* outputPtr = (TUint8*)(aDstBuf.Ptr());
       
  1774     TUint8* spsPtr;
       
  1775     TUint8* ppsPtr;
       
  1776 
       
  1777     TUint numSPS = 0;
       
  1778     TUint numPPS = 0;
       
  1779 
       
  1780     TUint totalSPSLength = 0;
       
  1781     TUint totalPPSLength = 0;
       
  1782 
       
  1783     TUint headerLength = aBuffer->Data().Length();
       
  1784     TUint endIndex = headerLength;
       
  1785 
       
  1786    	TInt nalType = 0;
       
  1787    	TUint nalLength;
       
  1788    	TUint nalIndex;
       
  1789     TUint nalOffset;
       
  1790 
       
  1791    	// Allocate memory for the temporary buffers
       
  1792    	HBufC8* temp1 = (HBufC8*) HBufC8::NewLC(1000);
       
  1793    	HBufC8* temp2 = (HBufC8*) HBufC8::NewLC(5000);
       
  1794 
       
  1795     spsPtr = const_cast<TUint8*>( temp1->Des().Ptr() );
       
  1796     ppsPtr = const_cast<TUint8*>( temp2->Des().Ptr() );
       
  1797 
       
  1798     TUint numNalUnits = inputPtr[endIndex-4] + (inputPtr[endIndex-3]<<8) + (inputPtr[endIndex-2]<<16) + (inputPtr[endIndex-1]<<24);
       
  1799     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL Nal Unit count: %d"), numNalUnits));    
       
  1800     
       
  1801 	// Move endIndex to point to the first NAL unit's offset information
       
  1802     endIndex = headerLength - numNalUnits*8 - 4;
       
  1803 	nalIndex = 0;
       
  1804 
       
  1805 	while (nalIndex < numNalUnits)
       
  1806         {
       
  1807     	nalIndex++;
       
  1808 
       
  1809     	TInt tmp1 = inputPtr[endIndex++];
       
  1810         TInt tmp2 = inputPtr[endIndex++]<<8;
       
  1811         TInt tmp3 = inputPtr[endIndex++]<<16;
       
  1812         TInt tmp4 = inputPtr[endIndex++]<<24;
       
  1813 
       
  1814     	nalOffset = tmp1 + tmp2 + tmp3 + tmp4;
       
  1815         PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL Nal Unit start offset: %d"), nalOffset));    	
       
  1816 
       
  1817     	tmp1 = inputPtr[endIndex++];
       
  1818         tmp2 = inputPtr[endIndex++]<<8;
       
  1819         tmp3 = inputPtr[endIndex++]<<16;
       
  1820         tmp4 = inputPtr[endIndex++]<<24;
       
  1821 
       
  1822     	nalLength = tmp1 + tmp2 + tmp3 + tmp4;
       
  1823         PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL Nal Unit length: %d"), nalLength));    	
       
  1824 
       
  1825 	   	nalType = inputPtr[nalOffset] & 0x1F;
       
  1826         PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL Nal Unit type: %d"), nalType));
       
  1827         
       
  1828 	   	if(nalType == 7)
       
  1829 		    {
       
  1830 	   		numSPS++;
       
  1831 
       
  1832 		    // First store the SPS unit length with two bytes
       
  1833    			spsPtr[totalSPSLength] = (nalLength >> 8) & 0xFF;
       
  1834     		spsPtr[totalSPSLength+1] = nalLength & 0xFF;
       
  1835 
       
  1836 			// Copy the SPS unit to the buffer
       
  1837 			Mem::Copy(&spsPtr[totalSPSLength+2], inputPtr+nalOffset , nalLength);
       
  1838 	        PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL stored SPS from offset: %d size: %d"), inputPtr+nalOffset, nalLength));			
       
  1839 			totalSPSLength += nalLength + 2;	// Two more for the size
       
  1840 		    }
       
  1841   		else if(nalType == 8)
       
  1842    		    {
       
  1843 			numPPS++;
       
  1844 
       
  1845 		    // First store the SPS unit length with two bytes
       
  1846    			ppsPtr[totalPPSLength] = (nalLength >> 8) & 0xFF;
       
  1847     		ppsPtr[totalPPSLength+1] = nalLength & 0xFF;
       
  1848 
       
  1849 			// Copy the SPS unit to the buffer
       
  1850 			Mem::Copy(&ppsPtr[totalPPSLength+2], inputPtr+nalOffset , nalLength);
       
  1851             PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderNALL stored PPS from offset: %d size: %d"), inputPtr+nalOffset, nalLength));			
       
  1852 			totalPPSLength += nalLength + 2;	// Two more for the size
       
  1853 	   	    }
       
  1854 		else
       
  1855    		    {
       
  1856    		    }
       
  1857         }
       
  1858 
       
  1859 	// When the header has been parsed, form the AVC Decoder Configuration Record
       
  1860 	outputPtr[0] = 0x01;	// configurationVersion
       
  1861 	// AVCProfileIndication contains the profile code as defined in the AVC specification
       
  1862     if (iFileCodecType & MP4_TYPE_AVC_PROFILE_BASELINE)
       
  1863         {
       
  1864         outputPtr[1] = 0x42;
       
  1865         outputPtr[2] = 0x80;    // Bitstream obeys all Baseline profile constraints.
       
  1866         // Profile compatibility, i.e. all 4 constrain set flags + reserved 4 zero bits
       
  1867         if ( iAVCOutputLevel == 101 )
       
  1868             {
       
  1869             outputPtr[2] |= 0x10; // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
       
  1870             }
       
  1871         // AVCLevelIndication contains the level code as defined in the AVC specification
       
  1872         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x0B : iAVCOutputLevel;
       
  1873         }
       
  1874     else if (iFileCodecType & MP4_TYPE_AVC_PROFILE_MAIN)
       
  1875         {
       
  1876         outputPtr[1] = 0x4D;
       
  1877         outputPtr[2] = 0x40;    // Bitstream obeys all main profile constraints.
       
  1878         if ( iAVCOutputLevel == 101 )
       
  1879             {
       
  1880             outputPtr[2] |= 0x10; // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
       
  1881             }
       
  1882         // AVCLevelIndication contains the level code as defined in the AVC specification
       
  1883         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x0B : iAVCOutputLevel;
       
  1884         }
       
  1885     else if (iFileCodecType & MP4_TYPE_AVC_PROFILE_HIGH)
       
  1886         {
       
  1887         outputPtr[1] = 0x64;
       
  1888         outputPtr[2] = 0x40;    // Bitstream obeys all Baseline profile constraints.
       
  1889         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x09 : iAVCOutputLevel;
       
  1890         }
       
  1891     else
       
  1892         {
       
  1893         User::Leave(KErrNotSupported);
       
  1894         }
       
  1895 
       
  1896 	// lengthSizeMinusOne indicates the length in bytes of the NALUnitLength field minus one.
       
  1897 	outputPtr[4] = 0x03; // 4 bytes
       
  1898 	outputPtr[4] |= 0x0FC; // 6 reserved bits (all 1)
       
  1899 	// numOfSequenceParameterSets indicates the number of sequence parameter sets
       
  1900 	outputPtr[5] = numSPS;
       
  1901 	outputPtr[5] |= 0xE0;  // 3 reserved bits (all 1)
       
  1902 
       
  1903 	TInt len = 6;
       
  1904 	// Copy the SPS unit(s) to the buffer
       
  1905 	Mem::Copy(&outputPtr[6], spsPtr , totalSPSLength);
       
  1906 	len += totalSPSLength;
       
  1907 	outputPtr[6+totalSPSLength] = numPPS;
       
  1908 	len += 1;
       
  1909 
       
  1910 	// Copy the PPS unit(s) to the buffer
       
  1911 	Mem::Copy(&outputPtr[6+totalSPSLength+1], ppsPtr , totalPPSLength);
       
  1912 	len += totalPPSLength;
       
  1913 	aDstBuf.SetLength(len);
       
  1914 
       
  1915 	CleanupStack::PopAndDestroy(temp2);
       
  1916 	CleanupStack::PopAndDestroy(temp1);
       
  1917 }
       
  1918 
       
  1919 // -----------------------------------------------------------------------------
       
  1920 // CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL
       
  1921 //
       
  1922 // Convert AVC specific decoder config info  from Bytestream (ElementaryStream) encapsulation to
       
  1923 // AVC Decoder Configuration Record -format
       
  1924 // -----------------------------------------------------------------------------
       
  1925 //
       
  1926 void CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL( CCMRMediaBuffer* aBuffer, TDes8& aDstBuf )
       
  1927     {
       
  1928     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL in")));
       
  1929 	TUint8* inputPtr = (TUint8*)(aBuffer->Data().Ptr());
       
  1930     TUint8* outputPtr = (TUint8*)(aDstBuf.Ptr());
       
  1931     TUint8* spsPtr;
       
  1932     TUint8* ppsPtr;
       
  1933 
       
  1934     TUint numSPS = 0;
       
  1935     TUint numPPS = 0;
       
  1936 
       
  1937     TUint totalSPSLength = 0;
       
  1938     TUint totalPPSLength = 0;
       
  1939 
       
  1940     TUint headerLength = aBuffer->Data().Length();
       
  1941     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL buffer length: %d"), headerLength));
       
  1942 
       
  1943    	TInt nalType = 0;
       
  1944 
       
  1945    	// Allocate memory for the temporary buffers
       
  1946    	HBufC8* temp1 = (HBufC8*) HBufC8::NewLC(1000);
       
  1947    	HBufC8* temp2 = (HBufC8*) HBufC8::NewLC(5000);
       
  1948 
       
  1949     spsPtr = const_cast<TUint8*>( temp1->Des().Ptr() );
       
  1950     ppsPtr = const_cast<TUint8*>( temp2->Des().Ptr() );
       
  1951 
       
  1952     // scan from beginning of buffer to end for SPS and PSP
       
  1953     TInt i = 0;
       
  1954     TInt j = 0;
       
  1955     for (i=0; i<headerLength; i++)
       
  1956     	{
       
  1957     	if ( inputPtr[i] == 0 &&
       
  1958     		 inputPtr[i+1] == 0 &&
       
  1959     		 inputPtr[i+2] == 0 &&
       
  1960     		 inputPtr[i+3] == 1 )
       
  1961     		{ // found bytestream header [00 00 00 01]
       
  1962     	    PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL found header at: %d"), i));
       
  1963     	   	nalType = inputPtr[i+4] & 0x1F;
       
  1964             PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL NAL type: %d"), nalType));
       
  1965     	   	if(nalType == 7) // SPS
       
  1966     	   		{
       
  1967     	   		numSPS++;
       
  1968     	   		// find length of SPS
       
  1969     	   		TInt j;
       
  1970     	   		for (j=4; i+j+3<headerLength; j++)
       
  1971     	   			{
       
  1972     	   	    	if ( inputPtr[i+j] == 0 &&
       
  1973     	   	    		 inputPtr[i+j+1] == 0 &&
       
  1974     	   	    		 inputPtr[i+j+2] == 0 &&
       
  1975     	   	    		 inputPtr[i+j+3] == 1 )
       
  1976     	   	    		{
       
  1977     	   	    		totalSPSLength = j-i-4;
       
  1978     	   	            PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL SPS length: %d, count: %d"), totalSPSLength, numSPS));
       
  1979     	   	    		break;
       
  1980     	   	    		}
       
  1981     	   			}
       
  1982     	   		// if we didn't find next bytestream header then this is last buffer
       
  1983     	   		if ( totalSPSLength == 0 )
       
  1984     	   			{
       
  1985     	   			totalSPSLength = headerLength - i - 4;
       
  1986                     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL SPS length: %d (last), count: %d"), totalSPSLength, numSPS));
       
  1987     	   			}
       
  1988 
       
  1989     		    // First store the SPS unit length with two bytes
       
  1990        			spsPtr[0] = (totalSPSLength >> 8) & 0xFF;
       
  1991         		spsPtr[1] = totalSPSLength & 0xFF;
       
  1992 
       
  1993         		// Copy the SPS unit to the buffer
       
  1994     			Mem::Copy(&spsPtr[2], &inputPtr[i+4] , totalSPSLength);
       
  1995     			totalSPSLength +=2;
       
  1996     	   		}
       
  1997     	   	else if ( nalType == 8 ) // PPS)
       
  1998     	   		{
       
  1999     	   		numPPS++;
       
  2000     	   		// find length of PPS
       
  2001     	   		for (j=4; i+j+3<headerLength; j++)
       
  2002     	   			{
       
  2003     	   	    	if ( inputPtr[i+j] == 0 &&
       
  2004     	   	    		 inputPtr[i+j+1] == 0 &&
       
  2005     	   	    		 inputPtr[i+j+2] == 0 &&
       
  2006     	   	    		 inputPtr[i+j+3] == 1 )
       
  2007     	   	    		{
       
  2008     	   	    		totalPPSLength = j-i-4;
       
  2009                         PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL PPS length: %d, count: %d"), totalPPSLength, numPPS));
       
  2010     	   	    		break;
       
  2011     	   	    		}
       
  2012     	   			}
       
  2013     	   		// if we didn't find next bytestream header then this is last buffer
       
  2014     	   		if ( totalPPSLength == 0 )
       
  2015     	   			{
       
  2016     	   			totalPPSLength = headerLength - i - 4;
       
  2017                     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL PPS length: %d (last), count: %d"), totalPPSLength, numPPS));
       
  2018     	   			}
       
  2019 
       
  2020     		    // First store the SPS unit length with two bytes
       
  2021     	   		ppsPtr[0] = (totalPPSLength >> 8) & 0xFF;
       
  2022     	   		ppsPtr[1] = totalPPSLength & 0xFF;
       
  2023 
       
  2024     			// Copy the SPS unit to the buffer
       
  2025     			Mem::Copy(&ppsPtr[2], &inputPtr[i+4], totalPPSLength);
       
  2026     	   		totalPPSLength +=2;
       
  2027     	   		}
       
  2028     		}
       
  2029     	}
       
  2030 
       
  2031 	// When the header has been parsed, form the AVC Decoder Configuration Record
       
  2032 	outputPtr[0] = 0x01;	// configurationVersion
       
  2033     // AVCProfileIndication contains the profile code as defined in the AVC specification
       
  2034     if (iFileCodecType & MP4_TYPE_AVC_PROFILE_BASELINE)
       
  2035         {
       
  2036         outputPtr[1] = 0x42;
       
  2037         outputPtr[2] = 0x80;    // Bitstream obeys all Baseline profile constraints.
       
  2038         // Profile compatibility, i.e. all 4 constrain set flags + reserved 4 zero bits
       
  2039         if ( iAVCOutputLevel == 101 )
       
  2040             {
       
  2041             outputPtr[2] |= 0x10; // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
       
  2042             }
       
  2043         // AVCLevelIndication contains the level code as defined in the AVC specification
       
  2044         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x0B : iAVCOutputLevel;
       
  2045         }
       
  2046     else if (iFileCodecType & MP4_TYPE_AVC_PROFILE_MAIN)
       
  2047         {
       
  2048         outputPtr[1] = 0x4D;
       
  2049         outputPtr[2] = 0x40;    // Bitstream obeys all main profile constraints.
       
  2050         if ( iAVCOutputLevel == 101 )
       
  2051             {
       
  2052             outputPtr[2] |= 0x10; // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
       
  2053             }
       
  2054         // AVCLevelIndication contains the level code as defined in the AVC specification
       
  2055         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x0B : iAVCOutputLevel;
       
  2056         }
       
  2057     else if (iFileCodecType & MP4_TYPE_AVC_PROFILE_HIGH)
       
  2058         {
       
  2059         outputPtr[1] = 0x64;
       
  2060         outputPtr[2] = 0x40;    // Bitstream obeys all Baseline profile constraints.
       
  2061         outputPtr[3] = (iAVCOutputLevel == 101) ? 0x09 : iAVCOutputLevel;
       
  2062         }
       
  2063     else
       
  2064         {
       
  2065         User::Leave(KErrNotSupported);
       
  2066         }
       
  2067     
       
  2068 	// lengthSizeMinusOne indicates the length in bytes of the NALUnitLength field minus one.
       
  2069 	outputPtr[4] = 0x03; // 4 bytes
       
  2070 	outputPtr[4] |= 0x0FC; // 6 reserved bits (all 1)
       
  2071 	// numOfSequenceParameterSets indicates the number of sequence parameter sets
       
  2072 	outputPtr[5] = numSPS;
       
  2073 	outputPtr[5] |= 0xE0;  // 3 reserved bits (all 1)
       
  2074 
       
  2075 	TInt len = 6;
       
  2076 
       
  2077 	// Copy the SPS unit(s) to the buffer
       
  2078 	Mem::Copy(&outputPtr[6], spsPtr , totalSPSLength);
       
  2079 	len += totalSPSLength;
       
  2080 	outputPtr[6+totalSPSLength] = numPPS;
       
  2081 	len += 1;
       
  2082 
       
  2083 	// Copy the PPS unit(s) to the buffer
       
  2084 	Mem::Copy(&outputPtr[6+totalSPSLength+1], ppsPtr , totalPPSLength);
       
  2085 	len += totalPPSLength;
       
  2086 	aDstBuf.SetLength(len);
       
  2087 
       
  2088 	CleanupStack::PopAndDestroy(temp2);
       
  2089 	CleanupStack::PopAndDestroy(temp1);
       
  2090     PRINT((_L("CCamC3GPDataSinkImp::ConvertAVCHeaderByteStreamL out")));
       
  2091 }
       
  2092 
       
  2093 // -----------------------------------------------------------------------------
       
  2094 // CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL
       
  2095 //
       
  2096 // Converts AVC frame from Bytestream (ElementaryStream) encapsulation to
       
  2097 // file format AVC sample structure by replacing bytestream headers with NAL unit sizes.
       
  2098 // -----------------------------------------------------------------------------
       
  2099 //
       
  2100 void CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizes( CCMRMediaBuffer* aBuffer )
       
  2101     {
       
  2102     PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL in")));
       
  2103     TUint8* inputPtr = (TUint8*)(aBuffer->Data().Ptr());
       
  2104     TUint headerLength = aBuffer->Data().Length();
       
  2105     PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL buffer length: %d"), headerLength));
       
  2106 
       
  2107     TInt nalLength = 0;
       
  2108     TBool moreThanOneNAL = EFalse;
       
  2109     TInt i = 0;
       
  2110     TInt j = 0;
       
  2111     for (i=0; i<headerLength; i++)
       
  2112         {
       
  2113         if ( inputPtr[i] == 0 &&
       
  2114              inputPtr[i+1] == 0 &&
       
  2115              inputPtr[i+2] == 0 &&
       
  2116              inputPtr[i+3] == 1 )
       
  2117             { // found bytestream header [00 00 00 01]
       
  2118             PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL found header at: %d"), i));
       
  2119             PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL NAL type: %d"), TInt(inputPtr[i+4] & 0x1F) ));
       
  2120             if (moreThanOneNAL)
       
  2121                 {// we found start of next NAL unit in memory buffer so update previous size
       
  2122                 nalLength = i-j-4; // 4 is the bytestream header
       
  2123                 PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL NAL length: %d"), nalLength));
       
  2124                 inputPtr[j] = TUint8((nalLength >> 24) & 0xff);
       
  2125                 inputPtr[j+1] = TUint8((nalLength >> 16) & 0xff);
       
  2126                 inputPtr[j+2] = TUint8((nalLength >> 8) & 0xff);
       
  2127                 inputPtr[j+3] = TUint8(nalLength & 0xff);
       
  2128                 }
       
  2129             moreThanOneNAL = ETrue;
       
  2130             j=i;
       
  2131             }
       
  2132         }
       
  2133     // and update last (or if only 1 NAL size:
       
  2134     nalLength = headerLength-j-4; // 4 is the bytestream header
       
  2135     PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL last NAL length: %d"), nalLength));
       
  2136     inputPtr[j] = TUint8((nalLength >> 24) & 0xff);
       
  2137     inputPtr[j+1] = TUint8((nalLength >> 16) & 0xff);
       
  2138     inputPtr[j+2] = TUint8((nalLength >> 8) & 0xff);
       
  2139     inputPtr[j+3] = TUint8(nalLength & 0xff);
       
  2140     PRINT((_L("CCamC3GPDataSinkImp::ConvertBytestreamHeadersToNALSizesL out")));
       
  2141 }
       
  2142 
       
  2143 // -----------------------------------------------------------------------------
       
  2144 // CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes
       
  2145 //
       
  2146 // Converts AVC frame from NAL (EGenericPayload) encapsulation to
       
  2147 // file format AVC sample structure by replacing NAL encapsulation with NAL unit sizes.
       
  2148 // -----------------------------------------------------------------------------
       
  2149 //
       
  2150 void CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes( CCMRMediaBuffer* aBuffer )
       
  2151     {
       
  2152     PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes in")));
       
  2153     TUint8* inputPtr = (TUint8*)(aBuffer->Data().Ptr());
       
  2154     TUint bufferLength = aBuffer->Data().Length();
       
  2155     PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes buffer length: %d"), bufferLength));
       
  2156 
       
  2157     // Offset to the end and get NAL unit count
       
  2158     TInt offset = bufferLength-4; //last 4 bytes are the NAL unit count
       
  2159     TInt nalCount = TInt(inputPtr[offset]) +
       
  2160                    (TInt(inputPtr[offset + 1]) << 8) +
       
  2161                    (TInt(inputPtr[offset + 2]) << 16) +
       
  2162                    (TInt(inputPtr[offset + 3]) << 24);
       
  2163 
       
  2164     TInt frameStart = 0;
       
  2165     TInt frameSize = 0;
       
  2166     TInt outputOffset = 0;
       
  2167     for(TInt i=0; i<nalCount; i++)
       
  2168         {//go through all NAL units in buffer
       
  2169         // Offset to the start of NAL Unit infos
       
  2170         offset = bufferLength-4-(8*nalCount); // 4 is the NAL unit count at end of buffer, 8 bytes used per NAL Unit for FrameStartOffset and FrameSize.
       
  2171 
       
  2172         // Get frame start offset
       
  2173         offset += 8*i;
       
  2174         frameStart = TInt(inputPtr[offset]) +
       
  2175                     (TInt(inputPtr[offset + 1]) << 8) +
       
  2176                     (TInt(inputPtr[offset + 2]) << 16) +
       
  2177                     (TInt(inputPtr[offset + 3]) << 24);
       
  2178 
       
  2179         PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes() NAL unit %d frame start: %d "), i, frameStart ));
       
  2180 
       
  2181         // Get frame size
       
  2182         offset += 4;
       
  2183         frameSize = TInt(inputPtr[offset]) +
       
  2184                    (TInt(inputPtr[offset + 1]) << 8) +
       
  2185                    (TInt(inputPtr[offset + 2]) << 16) +
       
  2186                    (TInt(inputPtr[offset + 3]) << 24);
       
  2187 
       
  2188        PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes() NAL unit %d frame size: %d "), i, frameSize ));
       
  2189        PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes() NAL unit %d type: %d "), i, TInt(inputPtr[frameStart] & 0x1F) ));
       
  2190 
       
  2191        iVideoBuffer[outputOffset] = TUint8((frameSize >> 24) & 0xff);
       
  2192        iVideoBuffer[outputOffset+1] = TUint8((frameSize >> 16) & 0xff);
       
  2193        iVideoBuffer[outputOffset+2] = TUint8((frameSize >> 8) & 0xff);
       
  2194        iVideoBuffer[outputOffset+3] = TUint8(frameSize & 0xff);
       
  2195 
       
  2196        Mem::Copy(iVideoBuffer+outputOffset+4, inputPtr+frameStart, frameSize);
       
  2197        outputOffset += 4 + frameSize; // 4 bytes for length information.
       
  2198        }
       
  2199     iVideoBufferFrameSize = outputOffset;
       
  2200     PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes() new video buffer size: %d "), iVideoBufferFrameSize ));
       
  2201     PRINT((_L("CCamC3GPDataSinkImp::ConvertNALEncapsulationToNALSizes out")));
       
  2202     }
       
  2203 
       
  2204 // -----------------------------------------------------------------------------
       
  2205 // CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName
       
  2206 // -----------------------------------------------------------------------------
       
  2207 //
       
  2208 void CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName( MP4FileName tempFileName )
       
  2209     {
       
  2210     PRINT((_L("CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName entering, tempFileName=%x, file count=%d"),tempFileName, iDeleteFileQueue->Count()));
       
  2211     MP4FileName* tempFileNamePtr = NULL;
       
  2212     TInt result = KErrNoMemory;
       
  2213 
       
  2214     // Add image to the queue.
       
  2215     tempFileNamePtr = new MP4FileName;
       
  2216     PRINT((_L("CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName tempFileName=%x, tempFileNamePtr=%x"), tempFileName, tempFileNamePtr));
       
  2217     if ( tempFileNamePtr && iDeleteFileQueue )
       
  2218         {
       
  2219         *tempFileNamePtr = tempFileName;
       
  2220         result = iDeleteFileQueue->Append( tempFileNamePtr );
       
  2221         }
       
  2222     if ( result != KErrNone ) // Append failed -> do sync remove
       
  2223         {
       
  2224         TInt err = wremove( tempFileName );
       
  2225         PRINT((_L("CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName wremove sync err=%d, tempFileName=%x"), err, tempFileName));
       
  2226         free(tempFileName);
       
  2227         tempFileName = 0;
       
  2228         if ( tempFileNamePtr )
       
  2229             {
       
  2230             delete tempFileNamePtr;
       
  2231             tempFileNamePtr = 0;
       
  2232             }
       
  2233         }
       
  2234     else  // Append OK, start async delete if not running already
       
  2235         {
       
  2236         if (iDeleteFileQueue->Count())
       
  2237             {
       
  2238 
       
  2239             if ( !iIdleDelete->IsActive() )
       
  2240                 {
       
  2241                 PRINT((_L("CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName() Start IdleDelete, file count=%d"), iDeleteFileQueue->Count()));
       
  2242                 iIdleDelete->Start( TCallBack( IdleDelete, this ) );
       
  2243                 }
       
  2244             }
       
  2245         }
       
  2246 
       
  2247     PRINT((_L("CCamC3GPDataSinkImp::M3GPMP4LibDeleteTempFileName exiting")));
       
  2248     }
       
  2249 
       
  2250 
       
  2251 // ---------------------------------------------------------------------------
       
  2252 // CCamC3GPDataSinkImp::IdleDelete
       
  2253 // ---------------------------------------------------------------------------
       
  2254 //
       
  2255 TInt CCamC3GPDataSinkImp::IdleDelete( TAny* aCont )
       
  2256     {
       
  2257     CCamC3GPDataSinkImp* appCont = static_cast<CCamC3GPDataSinkImp*>( aCont );
       
  2258     return ( appCont->DoIdleDelete() );
       
  2259     }
       
  2260 
       
  2261 // ---------------------------------------------------------------------------
       
  2262 // CCamC3GPDataSinkImp::DoIdleDelete
       
  2263 // ---------------------------------------------------------------------------
       
  2264 //
       
  2265 TInt CCamC3GPDataSinkImp::DoIdleDelete()
       
  2266     {
       
  2267     PRINT((_L("CCamC3GPDataSinkImp::DoIdleDelete() in, file count=%d"), iDeleteFileQueue->Count()));
       
  2268     TInt err = KErrNone;
       
  2269     MP4FileName tempFileName;
       
  2270     TInt filesLeft = EFalse;
       
  2271 
       
  2272     // Delete one file from queue
       
  2273     if ( iDeleteFileQueue )
       
  2274         {
       
  2275         if ( iDeleteFileQueue->Count() )
       
  2276             {
       
  2277             tempFileName = *(*iDeleteFileQueue)[0];
       
  2278             PRINT((_L("CCamC3GPDataSinkImp::DoIdleDelete index 0:tempFileName=%x %s"), tempFileName, tempFileName));
       
  2279             delete (*iDeleteFileQueue)[0];
       
  2280             iDeleteFileQueue->Remove( 0 );
       
  2281             err = wremove( tempFileName );
       
  2282             PRINT((_L("CCamC3GPDataSinkImp::DoIdleDelete wremove async err=%d, tempFileName=%x %s"), err, tempFileName, tempFileName));
       
  2283             err++; // remove compiler warning
       
  2284             free(tempFileName);
       
  2285             tempFileName = 0;
       
  2286             }
       
  2287 
       
  2288         // Start next deletion if queue is not empty
       
  2289         if ( iDeleteFileQueue->Count() )
       
  2290             {
       
  2291             PRINT((_L("CCamC3GPDataSinkImp::DoIdleDelete() continue, file count=%d"), iDeleteFileQueue->Count()));
       
  2292             filesLeft = ETrue;
       
  2293             }
       
  2294         }
       
  2295 
       
  2296     PRINT((_L("CCamC3GPDataSinkImp::DoIdleDelete() out")));
       
  2297     return ( filesLeft );
       
  2298     }
       
  2299 
       
  2300 
       
  2301 //  End of File