--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/vedengine/videoprocessor/src/movieprocessorimpl.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,6444 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Symbian Foundation License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation for movie processor
+*
+*/
+
+
+// Include Files
+
+#include "movieprocessorimpl.h"
+#include "statusmonitor.h"
+#include "activequeue.h"
+#include "mp4parser.h"
+#include "mp4composer.h"
+#include "videoencoder.h"
+#include "yuv2rgb12.h"
+#include "yuv2rgb16.h"
+#include "yuv2rgb24.h"
+#include "VideoProcessorAudioData.h"
+#include "DisplayChain.h"
+#include "VedRgb2YuvConverter.h"
+#include "vedaudiosettings.h"
+#include "vedvideosettings.h"
+#include "AudSong.h"
+#include "audioprocessor.h"
+#include "SizeEstimate.h"
+#include "vedavcedit.h"
+
+// Local Constants
+
+const TUint KReadBufInitSize = 512; // stream start buffer initial size
+//const TInt KVideoProcessorPriority = CActive::EPriorityHigh;
+const TUint KVideoQueueBlocks = 16;
+const TUint KVideoQueueBlockSize = 256;
+const TInt KDemuxPriority = CActive::EPriorityHigh;
+const TUint KInitialAudioBufferSize = 1024;
+const TUint KInitialVideoBufferSize = 10240;
+const TUint KMaxVideoSpeed = 1000;
+const TUint KVideoTimeScale = 5000; // for both normal & generated clips
+const TUint KAMRAudioTimeScale = 8000;
+
+const TUint KDiskSafetyLimit = 400000; // Amount of free disk space to leave unused
+
+_LIT(KTempFilePath ,"c:\\system\\temp\\"); // path for temp file used in image insertion
+
+// An assertion macro wrapper to clean up the code a bit
+#define VPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CMovieProcessorImpl"), EInvalidInternalState))
+
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x;
+#else
+#define PRINT(x)
+#endif
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMovieProcessorImpl* CMovieProcessorImpl::NewL()
+{
+ CMovieProcessorImpl* self = NewLC();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CMovieProcessorImpl* CMovieProcessorImpl::NewLC()
+{
+ CMovieProcessorImpl* self = new (ELeave) CMovieProcessorImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CMovieProcessorImpl
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMovieProcessorImpl::CMovieProcessorImpl()
+: CActive(EPriorityNormal), iReadImageDes(0,0), iReadDes(0, 0)
+{
+ // Reset state
+ iState = EStateIdle;
+ iDataFormat = EDataAutoDetect;
+ iAudioFramesInSample = KVedAudioFramesInSample;
+
+ iStartTransitionEffect = EVedStartTransitionEffectNone;
+ iMiddleTransitionEffect = EVedMiddleTransitionEffectNone;
+ iPreviousMiddleTransitionEffect = EVedMiddleTransitionEffectNone;
+ iEndTransitionEffect = EVedEndTransitionEffectNone;
+ iSpeed = KMaxVideoSpeed;
+ iColorEffect = EVedColorEffectNone;
+ iNumberOfVideoClips=1;
+ iTr.iTrPrevNew = -1;
+ iTr.iTrPrevOrig = -1;
+ iStartFrameIndex = -1;
+ iMovieSizeLimit = 0;
+ iFrameParametersSize = 0;
+
+ // We are now properly initialized
+ iState = EStateIdle;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::~CMovieProcessorImpl
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CMovieProcessorImpl::~CMovieProcessorImpl()
+{
+
+ Cancel();
+
+ TInt error = KErrNone;
+
+ TRAP(error, DoCloseVideoL());
+
+ DeleteClipStructures();
+
+ if (iFrameParameters)
+ {
+ User::Free(iFrameParameters);
+ iFrameParameters = 0;
+ }
+
+ if (iVideoClipParameters)
+ {
+ User::Free(iVideoClipParameters);
+ iVideoClipParameters = 0;
+ }
+
+ if (iOutAudioBuffer) {
+ delete iOutAudioBuffer;
+ iOutAudioBuffer=0;
+ }
+
+ if (iOutVideoBuffer) {
+ delete iOutVideoBuffer;
+ iOutVideoBuffer=0;
+ }
+
+ // although this should be released by VideoEditorEngine,
+ // the following is still needed in case of leave
+
+ if(iDemux)
+ {
+ delete iDemux;
+ iDemux = 0;
+ }
+
+ if(iVideoProcessor)
+ {
+ delete iVideoProcessor;
+ iVideoProcessor = 0;
+ }
+
+ if (iComposer) {
+ delete iComposer;
+ iComposer = 0;
+ }
+
+ if (iAudioProcessor)
+ {
+ delete iAudioProcessor;
+ iAudioProcessor = 0;
+ }
+
+ if(iImageComposer)
+ {
+ delete iImageComposer;
+ iImageComposer=0;
+ }
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+
+ if (iYuvImageBuf)
+ {
+ User::Free(iYuvImageBuf);
+ iYuvImageBuf=0;
+ }
+
+ if(iVideoEncoder)
+ {
+ delete iVideoEncoder;
+ iVideoEncoder = 0;
+ }
+
+ if(iParser)
+ {
+ delete iParser;
+ iParser = 0;
+ }
+ if(iVideoQueue)
+ {
+ delete iVideoQueue;
+ iVideoQueue = 0;
+ }
+
+ if (iWaitScheduler)
+ {
+ delete iWaitScheduler;
+ iWaitScheduler = 0;
+ }
+
+ if(iMonitor)
+ {
+ delete iMonitor;
+ iMonitor = 0;
+ }
+
+ if (iReadBuf)
+ User::Free(iReadBuf);
+
+ if (iRgbBuf)
+ {
+ delete iRgbBuf;
+ iRgbBuf = 0;
+ }
+
+ if (iOutBitmap)
+ {
+ delete iOutBitmap;
+ iOutBitmap = 0;
+ }
+
+ if (iSizeEstimate)
+ {
+ delete iSizeEstimate;
+ iSizeEstimate = 0;
+ }
+
+ if (iAvcEdit)
+ {
+ delete iAvcEdit;
+ iAvcEdit = 0;
+ }
+
+ if (iImageYuvConverter)
+ {
+ delete iImageYuvConverter;
+ iImageYuvConverter = 0;
+ }
+
+ // for transition effect
+ if ( iFsConnected )
+ {
+ TRAP(error, CloseTransitionInfoL());
+ iFs.Close();
+ iFsConnected = EFalse;
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ConstructL()
+{
+
+ // Allocate stream reading buffer
+ iReadBuf = (TUint8*) User::AllocL(KReadBufInitSize);
+ iBufLength = KReadBufInitSize;
+
+ iClipFileName.Zero();
+ iOutputMovieFileName.Zero();
+
+ iWaitScheduler = new (ELeave) CActiveSchedulerWait;
+
+ // Add to active scheduler
+ CActiveScheduler::Add(this);
+
+ iSizeEstimate = CSizeEstimate::NewL(this);
+
+ iState = EStateIdle;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::StartMovieL
+// Prepares the processor for processing a movie and starts processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::StartMovieL(CVedMovieImp* aMovie, const TDesC& aFileName, RFile* aFileHandle,
+ MVedMovieProcessingObserver* aObserver)
+{
+
+ PRINT((_L("CMovieProcessorImpl::StartMovieL() begin")))
+
+ // reset member variables
+ ResetL();
+
+ // get arguments
+ iMovie = aMovie;
+ if (!iMovie)
+ User::Leave(KErrArgument);
+
+ iOutputMovieFileName = aFileName;
+ iOutputFileHandle = aFileHandle;
+
+ CVedMovieImp* movie = (iMovie);
+ iObserver = aObserver;
+
+ if (!iObserver)
+ User::Leave(KErrArgument);
+
+ if (iMonitor)
+ {
+ delete iMonitor;
+ iMonitor = 0;
+ }
+
+ // Create a status monitor object:
+ iMonitor = new (ELeave) CStatusMonitor(iObserver, this, aMovie);
+ iMonitor->ConstructL();
+
+ // update movie properties
+ iFramesProcessed=0;
+ iNumberOfVideoClips = iMovie->VideoClipCount();
+ iNumberOfAudioClips = iMovie->AudioClipCount();
+
+ // calculate total movie duration for progress bar: video & audio tracks.
+ // in milliseconds
+ iTotalMovieDuration = TInt64(2) * ( movie->Duration().Int64()/1000 );
+
+ for (TInt i = 0; i < iNumberOfVideoClips; i++)
+ {
+ CVedVideoClip* currentClip = movie->VideoClip(i);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+
+ // Take time to generate a clip into account
+ if (currentInfo->Class() == EVedVideoClipClassGenerated)
+ {
+ iTotalMovieDuration += currentInfo->Duration().Int64()/1000;
+ }
+ }
+
+ // set media types
+ SetOutputMediaTypesL();
+
+ // get transcode factors: bitstream mode & time inc. resolution
+ GetTranscodeFactorsL();
+
+ // set video transcoding parameters
+ SetupTranscodingL();
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ // check if AVC editing is involved
+ TBool avcEditing = ( iOutputVideoType == EVideoAVCProfileBaseline );
+ for(TInt i = 0; i < movie->VideoClipCount() && avcEditing == EFalse; i++)
+ {
+ CVedVideoClip* currentClip = movie->VideoClip(i);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+
+ if( currentInfo->Class() == EVedVideoClipClassFile &&
+ (currentInfo->VideoType() == EVedVideoTypeAVCBaselineProfile) )
+ {
+ avcEditing = ETrue;
+ break;
+ }
+ }
+
+ if (avcEditing)
+ {
+ // create AVC editing instance
+ iAvcEdit = CVedAVCEdit::NewL();
+ }
+
+ if (iOutputVideoType == EVideoAVCProfileBaseline)
+ {
+ // set level
+ iAvcEdit->SetOutputLevel( GetOutputAVCLevel() );
+ }
+
+#endif
+
+ // Check
+ //iOutputAudioType = EAudioAMR; // default is Amr if all are generated
+
+ if ( iFsConnected == EFalse )
+ {
+ User::LeaveIfError( iFs.Connect() );
+ iFsConnected = ETrue;
+ }
+
+ if (iNumberOfVideoClips)
+ {
+ iStartTransitionEffect = aMovie->StartTransitionEffect();
+ iEndTransitionEffect = aMovie->EndTransitionEffect();
+ CloseTransitionInfoL();
+ }
+
+ iImageEncodeProcFinished = 0; // to indicate whether encode images process is finished
+ iImageEncodedFlag = 0; // has an image been encoded
+ iFirstTimeProcessing = 0;
+ iTotalImagesProcessed = 0;
+ iImageClipCreated = 0; // has an image clip been created
+
+ iImageVideoTimeScale = KVideoTimeScale; // Initializing to standard value
+ iGetFrameInProgress = 0;
+ iOutputAudioTimeSet = 0;
+ iOutputVideoTimeSet = 0;
+ iAllGeneratedClips = 0; // Indicates if all the clips in the movie are generated clips - 0 indicates false
+ iEncodeInProgress = 0; // Indicates encoding is not in progress
+ iFirstClipHasNoDecInfo = EFalse;
+
+ // Allocate memory for frame parameters array
+ if (iFrameParameters)
+ User::Free(iFrameParameters);
+
+ iFrameParameters = 0;
+ iFrameParameters = (struct TFrameParameters *)User::AllocL(iFrameParametersSize * sizeof(struct TFrameParameters));
+ Mem::Fill(iFrameParameters, iFrameParametersSize * sizeof(TFrameParameters), 0);
+
+ InitializeClipStructuresL();
+
+ // second pass starts here
+ // load first clip properties
+ iVideoClipNumber=0;
+ iAudioClipNumber=0;
+
+ if (iNumberOfVideoClips)
+ iVideoClip = movie->VideoClip(iVideoClipNumber);
+
+ // if clip is not file-based, then call some other initializer
+ TInt firstClipIsGenerated = 0;
+ iFirstClipIsGen = EFalse;
+
+ // what if iNumberOfVideoClips == 0, this will fail !
+ if(iNumberOfVideoClips && iVideoClip->Info()->Class() == EVedVideoClipClassGenerated)
+ {
+ // since frame parameters are not available here, use temporary instantiation for composer
+ TemporaryInitializeGeneratedClipL();
+ // note that we may need to create a parser temporarily
+ firstClipIsGenerated = 1;
+ iFirstClipIsGen = ETrue;
+ }
+ else
+ {
+ InitializeClipL(); // check details inside initialization
+ }
+
+ if(iOutputAudioType == EAudioAMR)
+ {
+ if( iAudioType == EAudioNone)
+ iAudioType = EAudioAMR;
+ iAudioFramesInSample = KVedAudioFramesInSample;
+ }
+
+ else if(iOutputAudioType == EAudioAAC)
+ {
+ if( iAudioType == EAudioNone)
+ {
+ iAudioType = EAudioAAC;
+ iFirstClipHasNoDecInfo = ETrue; // because it has no audio so it will have no decoder specific Info
+ }
+ iAudioFramesInSample = 1;
+ }
+
+
+ VPASSERT(!iComposer);
+ // initialize composer
+ if (iOutputFileHandle)
+ iComposer = CMP4Composer::NewL(iOutputFileHandle, (CParser::TVideoFormat)iOutputVideoType, (CParser::TAudioFormat)iOutputAudioType, iAvcEdit);
+ else
+ iComposer = CMP4Composer::NewL(iOutputMovieFileName, (CParser::TVideoFormat)iOutputVideoType, (CParser::TAudioFormat)iOutputAudioType, iAvcEdit);
+
+ iFramesProcessed = 0;
+ iStartingProcessing = ETrue;
+
+ VPASSERT(iOutputVideoTimeScale);
+ VPASSERT(iOutputAudioTimeScale);
+ VPASSERT(iAudioFramesInSample);
+
+ // write video & audio descriptions
+ CComposer::TStreamParameters streamParameters;
+
+ if(iAllGeneratedClips == 0) // if all were generated initialize to default
+ {
+ if (iNumberOfVideoClips)
+ {
+ streamParameters = (CComposer::TStreamParameters &)iParser->iStreamParameters;
+ TSize tmpSize = iMovie->Resolution();
+ streamParameters.iVideoWidth = tmpSize.iWidth; /* iVideoParameters.iWidth; */
+ streamParameters.iVideoHeight = tmpSize.iHeight; /* iVideoParameters.iHeight; */
+ streamParameters.iHaveAudio = ETrue; //because u always insert silent amr frames atleast//aac frames
+ if(iOutputAudioType == EAudioAMR)
+ streamParameters.iAudioFormat = (CComposer::TAudioFormat)CComposer::EAudioFormatAMR;
+
+ else if(iOutputAudioType == EAudioAAC)
+ streamParameters.iAudioFormat = (CComposer::TAudioFormat)CComposer::EAudioFormatAAC; //if amr out is amr else aac if none it will be none
+
+ }
+ else
+ {
+ // No video, only audio; generate black frames. Can't use iParser->iStreamParameters since iParser doesn't exist
+ // SetHeaderDefaults() checked the resolution from movie to iVideoParameters
+ streamParameters.iVideoWidth = iVideoParameters.iWidth;
+ streamParameters.iVideoHeight = iVideoParameters.iHeight;
+ }
+ }
+ else
+ {
+
+ /* since all clips inserted are generated */
+ iVideoType = iOutputVideoType;
+
+ VPASSERT( (iVideoType == EVideoH263Profile0Level10) ||
+ (iVideoType == EVideoH263Profile0Level45) ||
+ (iVideoType == EVideoMPEG4) ||
+ (iVideoType == EVideoAVCProfileBaseline) );
+
+ streamParameters.iCanSeek = ETrue;
+ streamParameters.iNumDemuxChannels = 1; /* Because video will be there */
+ TTimeIntervalMicroSeconds movduration = TTimeIntervalMicroSeconds(movie->Duration());
+ TInt64 alllength = movduration.Int64();
+ streamParameters.iAudioLength = I64INT(alllength);
+ streamParameters.iVideoLength = I64INT(alllength);
+ streamParameters.iStreamLength = I64INT(alllength);
+ streamParameters.iVideoWidth = iVideoParameters.iWidth;
+ streamParameters.iVideoHeight = iVideoParameters.iHeight;
+
+ if (iOutputAudioType == EAudioAMR)
+ {
+ streamParameters.iAudioFormat = (CComposer::TAudioFormat) CComposer::EAudioFormatAMR;
+ streamParameters.iHaveVideo = ETrue;
+ streamParameters.iNumDemuxChannels++;
+ streamParameters.iAudioFramesInSample = KVedAudioFramesInSample;
+ iAudioFramesInSample = KVedAudioFramesInSample;
+ }
+
+ else if (iOutputAudioType == EAudioAAC)
+ {
+ streamParameters.iAudioFormat = (CComposer::TAudioFormat) CComposer::EAudioFormatAAC;
+ streamParameters.iHaveVideo = ETrue;
+ streamParameters.iNumDemuxChannels++;
+ streamParameters.iAudioFramesInSample = 1;
+ iAudioFramesInSample = 1; // Same as above
+ }
+
+ else
+ {
+
+ streamParameters.iAudioFormat = (CComposer::TAudioFormat) CComposer::EAudioFormatNone;
+ streamParameters.iHaveAudio =EFalse;
+ streamParameters.iAudioLength =0; /* reset audio length as it was set to videolength */
+ streamParameters.iAudioFramesInSample = KVedAudioFramesInSample;
+ iAudioFramesInSample = KVedAudioFramesInSample;
+ }
+
+ streamParameters.iAudioTimeScale = KAMRAudioTimeScale;
+ streamParameters.iVideoTimeScale = iImageVideoTimeScale;
+ iOutputVideoTimeScale = iImageVideoTimeScale;
+ iOutputAudioTimeScale = KAMRAudioTimeScale;
+
+ }
+
+ TAudFileProperties outProp = iMovie->Song()->OutputFileProperties();
+
+ if (iMovie->Song()->ClipCount(KAllTrackIndices) > 0)
+ {
+ if ( outProp.iAudioType == EAudAAC_MPEG4)
+ {
+ iOutputAudioTimeScale = outProp.iSamplingRate;
+
+ }
+ }
+
+ streamParameters.iVideoFormat = (CComposer::TVideoFormat)iOutputVideoType;
+ streamParameters.iStreamBitrate = iMovie->VideoStandardBitrate();
+ iComposer->ComposeHeaderL(streamParameters, iOutputVideoTimeScale, iOutputAudioTimeScale, iAudioFramesInSample);
+
+ if( firstClipIsGenerated == 1 )
+ {
+ // since first clip is generated, destroy parser
+ iMonitor->PrepareComplete();
+ iMonitor->ProcessingStarted(iStartingProcessing);
+ iStartingProcessing = EFalse;
+ iState = EStateProcessing;
+
+ // since first clip is generated, destroy parser
+ if(iAllGeneratedClips == 1)
+ {
+ if(iParser)
+ {
+ delete iParser;
+ iParser =0;
+ }
+ }
+ }
+
+ PRINT((_L("CMovieProcessorImpl::StartMovieL() end")))
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SetOutputMediaTypesL
+// Set output audio/video types
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::SetOutputMediaTypesL()
+{
+
+ CVedMovieImp* movie = (iMovie);
+
+ if( movie->VideoType() == EVedVideoTypeH263Profile0Level10 )
+ iOutputVideoType = EVideoH263Profile0Level10;
+
+ else if ( movie->VideoType() == EVedVideoTypeH263Profile0Level45 )
+ iOutputVideoType = EVideoH263Profile0Level45;
+
+ else if ( movie->VideoType() == EVedVideoTypeMPEG4SimpleProfile )
+ iOutputVideoType = EVideoMPEG4;
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ else if ( movie->VideoType() == EVedVideoTypeAVCBaselineProfile )
+ iOutputVideoType = EVideoAVCProfileBaseline;
+#endif
+
+ else
+ User::Leave(KErrArgument);
+
+ CAudSong* songPointer = movie->Song();
+ if ( songPointer->ClipCount(KAllTrackIndices) > 0 )
+ {
+ if( movie->AudioType() == EVedAudioTypeAMR )
+ iOutputAudioType = EAudioAMR;
+
+ else if ( movie->AudioType() == EVedAudioTypeAAC_LC )
+ iOutputAudioType = EAudioAAC;
+ else
+ User::Leave(KErrArgument);
+ }
+ else
+ {
+ // no audio
+ iOutputAudioType = EAudioNone;
+ }
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetTranscodeFactorsL
+// Retrieve bitstream modes for input clips
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::GetTranscodeFactorsL()
+{
+
+ if (!iNumberOfVideoClips)
+ return;
+
+ CVedMovieImp* movie = (iMovie);
+
+ iThumbnailInProgress = ETrue;
+
+ InitializeClipStructuresL();
+
+ for(TInt i = 0; i < movie->VideoClipCount(); i++)
+ {
+ CVedVideoClip* currentClip = movie->VideoClip(i);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+
+ if( currentInfo->Class() == EVedVideoClipClassFile )
+ {
+ TVedTranscodeFactor factor;
+
+ if ( currentInfo->FileHandle() )
+ {
+ iClipFileName.Zero();
+ iClipFileHandle = currentInfo->FileHandle();
+ }
+ else
+ {
+ iClipFileHandle = NULL;
+ iClipFileName = currentInfo->FileName();
+ }
+
+ InitializeClipL(); // opens the file & parses header
+ // open demux & decoder
+
+ // Calculate the number of frames in the output clip
+ iFrameParametersSize += iParser->GetNumberOfVideoFrames();
+
+ iState = EStateProcessing;
+
+ TInt error = iVideoProcessor->GetTranscodeFactorL(factor);
+
+ if (error != KErrNone)
+ User::Leave(error);
+
+ if ( ((factor.iStreamType == EVedVideoBitstreamModeMPEG4Resyn)
+ || (factor.iStreamType == EVedVideoBitstreamModeMPEG4DP)
+ || (factor.iStreamType == EVedVideoBitstreamModeMPEG4DP_RVLC)
+ || (factor.iStreamType == EVedVideoBitstreamModeMPEG4Resyn_DP)
+ || (factor.iStreamType == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC))
+ && ( currentClip->Info()->Resolution() == movie->Resolution() )
+ && ( iOutputVideoType != EVideoAVCProfileBaseline ) )
+ {
+ // we do compressed domain transcoding for this clip, and it has
+ // other mpeg4 modes than the regular; we need to ensure the VOS/VOL header
+ // has the resync marked flag enabled
+ iMpeg4ModeTranscoded = ETrue;
+ }
+
+ currentInfo->SetTranscodeFactor(factor);
+
+ DoCloseVideoL(); // close all
+
+ if (iAvcEdit)
+ {
+ delete iAvcEdit;
+ iAvcEdit = 0;
+ }
+ }
+ else
+ {
+ // Calculate the number of frames in the output clip
+ iFrameParametersSize += (TInt) currentInfo->VideoFrameCount();
+ }
+ }
+
+ iThumbnailInProgress = EFalse;
+ iState = EStateIdle;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SetupTranscodingL
+// Set video transcoding parameters
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::SetupTranscodingL()
+{
+
+ if (!iNumberOfVideoClips)
+ return;
+
+ CVedMovieImp* tmovie = (iMovie);
+ TBool transitionExists = EFalse;// Assume there are no middle transitions in any clip
+ TBool cutExists = EFalse; // Assuming there is no cut in any clip
+ TBool blackFrames = EFalse; // Assume there is no need to encode black frames in the end
+ TBool firstClipIsGen = EFalse;
+ TBool firstClipIsFullTranscoded = EFalse;
+ TBool clipFullTranscodingExists = EFalse;
+
+ // Vos issues if first clip uses encoder
+ TBool atleastOneH263 = EFalse;
+ TBool atleastOneMPEG4 = EFalse;
+// TBool atleastOneAVC = EFalse;
+ TBool differentModesExist = EFalse;
+
+ // initially assume no mpeg4 files so no streammode
+ TVedVideoBitstreamMode streamMode = EVedVideoBitstreamModeUnknown;
+ TBool atleastOneGenerated = EFalse; // assuming that there are no generated clips
+ TBool allGeneratedClips = ETrue; // asssuming all are generated
+ iModeTranslationRequired = EFalse; // no need for translation in all generated
+
+ TSize outputVideoResolution = tmovie->Resolution(); // since movie resolution is minimum resolution
+
+ for(TInt i = 0; i < tmovie->VideoClipCount(); i++)
+ {
+ CVedVideoClip* currentClip = tmovie->VideoClip(i);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+ if( currentInfo->Class() == EVedVideoClipClassFile )
+ {
+ allGeneratedClips = EFalse; // there is a file based clip
+
+ if( (currentInfo->VideoType() == EVedVideoTypeH263Profile0Level10) ||
+ (currentInfo->VideoType() == EVedVideoTypeH263Profile0Level45) )
+ {
+ // if there is even one H263 output is H263
+ atleastOneH263 = ETrue;
+ }
+ else if(currentInfo->VideoType() == EVedVideoTypeAVCBaselineProfile)
+ {
+// atleastOneAVC = ETrue;
+ }
+ else
+ {
+ if(currentInfo->VideoType() == EVedVideoTypeMPEG4SimpleProfile) // if there is even one H263 output is H263
+ {
+ atleastOneMPEG4 = ETrue;
+ if(streamMode == EVedVideoBitstreamModeUnknown)
+ {
+ // since previously no mpeg4 was found to set streammode
+ streamMode = currentInfo->TranscodeFactor().iStreamType;
+ }
+ else
+ {
+ if(streamMode != currentInfo->TranscodeFactor().iStreamType) // different modes in Mpeg4
+ differentModesExist = ETrue;
+ }
+ }
+ else
+ {
+ //Error - improper or unsupported type file
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ // Here check if any clip is cut and also if first clip is cut
+ TTimeIntervalMicroSeconds cutinTime = TTimeIntervalMicroSeconds(currentClip->CutInTime());
+ if(cutinTime != TTimeIntervalMicroSeconds(0))
+ {
+ // cut does exist so encoder will be used in at least one clip
+ if(i==0) // which means cut exists in first clip itself
+ {
+ iFirstClipIsCut = ETrue;
+ }
+ cutExists = ETrue;
+ }
+
+ // check if the clip will be full transcoded also as then we can
+ // decide whether to change VOS bit and to set ModeTranslation as all would be encoded again
+ TSize currClipRes = currentInfo->Resolution();
+ if( ( (outputVideoResolution.iWidth != currClipRes.iWidth) &&
+ (outputVideoResolution.iHeight != currClipRes.iHeight) ) ||
+ ( iOutputVideoType == EVideoMPEG4 && currentInfo->VideoType() == EVedVideoTypeAVCBaselineProfile ) )
+ {
+ if(i == 0)
+ {
+ firstClipIsFullTranscoded = ETrue; //for VOS bit change
+ }
+ clipFullTranscodingExists = ETrue;
+ }
+ }
+ else
+ {
+ atleastOneGenerated = ETrue;
+ if(i == 0) // then first clip is generated
+ {
+ firstClipIsGen = ETrue;
+ }
+ }
+
+ if( i != tmovie->VideoClipCount()-1 )
+ {
+ if(tmovie->MiddleTransitionEffect(i) != EVedMiddleTransitionEffectNone )
+ {
+ // this is required to check if any clips have
+ // middle transitions so mode translation will be required
+ transitionExists = ETrue; // even if all clips are of same mode
+ }
+ }
+ }
+
+ if( (TVedStartTransitionEffect)tmovie->StartTransitionEffect() != EVedStartTransitionEffectNone )
+ {
+ // even if all clips are of same mode but if it is different than what encoder uses transcoding is needed
+ transitionExists = ETrue;
+ }
+
+ if( (TVedEndTransitionEffect)tmovie->EndTransitionEffect() != EVedEndTransitionEffectNone)
+ {
+ // even if all clips are of same mode but if it is different than what encoder uses transcoding is needed
+ transitionExists = ETrue;
+ }
+ if ( tmovie->Duration().Int64()/1000 > (tmovie->VideoClip(iNumberOfVideoClips-1)->EndTime().Int64()/1000) )
+ {
+ // movie is longer than video track => black frames are encoded in the end => even if all clips are of same mode but if it is different than what encoder uses transcoding is needed
+ blackFrames = ETrue;
+ }
+
+ if(iOutputVideoType == EVideoMPEG4) // if different modes dont exist then if output is Mpeg4
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), output type = MPEG-4")))
+
+ if(differentModesExist)
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), different modes exist")))
+
+ // if there are differnet mode Mpeg4's then mode translation is required
+ iModeTranslationRequired = ETrue; // regardless of there being generated clips
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), different modes don't exist")))
+
+ if(atleastOneGenerated) // if there are any generated clips
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), at least one generated")))
+
+ if(atleastOneMPEG4) // if there is one Mpeg4 clip atleast
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), at least one MPEG-4")))
+
+ if( (streamMode == EVedVideoBitstreamModeMPEG4Regular) ) //generated clips mode will be regular so u need to convert others
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), streamMode is regular")))
+
+ // if all are regular mode no need to change mode
+ iModeTranslationRequired = EFalse;
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), streamMode != regular")))
+
+ // to regular (with resync)
+ iModeTranslationRequired = ETrue;
+ }
+ }
+ else
+ {
+ if(atleastOneH263)
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), at least one H.263")))
+ iModeTranslationRequired = ETrue;
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), all are generated")))
+ // all are generated no h263 or mpeg4
+ iModeTranslationRequired = EFalse;
+ }
+ }
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), no generated clips")))
+
+ if(atleastOneH263)
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), at least one H.263")))
+ iModeTranslationRequired = ETrue;
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::SetupTranscodingL(), no H.263")))
+ // still open if we have MPEG-4 nonregular + encoding
+ iModeTranslationRequired = EFalse;
+ }
+ }
+ }
+ }
+ else
+ {
+ // output is H263 or AVC so mode translation not required
+ iModeTranslationRequired = EFalse;
+ }
+
+ // make decision of mode translation based on whether there
+ // was a cut or transition or resolution transcoding in any clip
+
+ if(iOutputVideoType == EVideoMPEG4) // if output is Mpeg4
+ {
+ if ((!allGeneratedClips) && (streamMode != EVedVideoBitstreamModeMPEG4Regular)) // in case of differentModesExist, iModeTranslationRequired is already ETrue
+ {
+ // If we need to encode smth but not all (if all generated => no mix), encoding results in regular stream.
+ // However, if input has nonregular, we need to translate the mode
+ if(transitionExists || clipFullTranscodingExists || cutExists || blackFrames)
+ {
+ iModeTranslationRequired = ETrue;
+ }
+ }
+ // make Decision for changing the Vos of the output movie based on whether the first frame would be encoded
+ if(firstClipIsGen || firstClipIsFullTranscoded || ((TVedStartTransitionEffect)tmovie->StartTransitionEffect() != EVedStartTransitionEffectNone) || iFirstClipIsCut )
+ {
+ iFirstClipUsesEncoder = ETrue; // this indicates that you may need to change Vos bit but final decision is
+ } // done based on whether it was due to cut on the fly
+ }
+
+}
+
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CreateImage3GPFilesL
+// creates the necessary 3gp files from the given frames
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::CreateImage3GPFilesL(TVideoOperation aCreateMode)
+{
+
+ if (iProcessingCancelled)
+ return KErrNone;
+
+ if(aCreateMode == EVideoEncodeFrame)
+ {
+ // encode frame
+ TTimeIntervalMicroSeconds inMicroSeconds = TTimeIntervalMicroSeconds(iVideoClip->Info()->Generator()->VideoFrameStartTime(iTotalImagesProcessed));
+
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ iVideoEncoder->EncodeFrameL(iReadImageDes, iStatus, inMicroSeconds);
+
+ // EncodeGiven
+ iImageEncodedFlag = 1;
+ iEncodeInProgress = 1;
+
+ return KErrNone;
+ }
+ else
+ {
+ // a frame has been encoded, write it to output 3gp buffer
+
+ // composer composing the movie
+ if(iStatus == KErrNone)
+ {
+ TBool isKeyFrame = 0;
+ TPtrC8 buf(iVideoEncoder->GetBufferL(isKeyFrame));
+
+ TBool modeChanged = EFalse;
+
+ if ( iTotalImagesProcessed == 1 && iVideoType == EVideoMPEG4 )
+ {
+ modeChanged = ETrue;
+ }
+
+ /* composing is based on isIntra only */
+ TBool firstFrame = EFalse;
+ if(iTotalImagesProcessed == 1)
+ {
+ firstFrame = ETrue;
+
+ // VOS header size is parsed in composer for MPEG-4
+ iMP4SpecificSize = 0;
+ }
+
+ TInt64 durntTest = iVideoClip->Info()->Generator()->VideoFrameDuration(iTotalImagesProcessed-1).Int64();
+ TInt64 durntsix = TInt64(((I64REAL(durntTest)/(TReal)1000)*(TReal) iImageVideoTimeScale) +0.5);
+ TInt durnt = I64INT(durntsix);
+ /* converting to ticks */
+ durnt = (durnt)/1000;
+
+ iGeneratedProcessed += durntTest/1000;
+ IncProgressBar(); /* indicate to gui about progress */
+
+ iImageComposer->WriteFrames((TDesC8&)buf, buf.Size(), durnt, isKeyFrame ,
+ 1/*numberOfFrames*/, CMP4Composer::EFrameTypeVideo, iMP4SpecificSize,modeChanged,
+ firstFrame,iVideoClip->Info()->TranscodeFactor().iStreamType, ETrue);
+
+ iVideoEncoder->ReturnBuffer();
+ }
+ /* end composing */
+
+ return KErrNone;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ProcessImageSetsL
+// Prepares for creating the necessary 3gp files from the given frames
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::ProcessImageSetsL(TVideoOperation aCreateMode)
+{
+
+ if (iProcessingCancelled)
+ return KErrNone;
+
+ if(iTotalImagesProcessed == 0 && iImageEncodeProcFinished == 0)
+ {
+ TFileName outputFileName = TPtrC(KTempFilePath);
+ iCurrentMovieName = outputFileName;
+ iCurrentMovieName.Append( _L( "Im" ) );
+ iCurrentMovieName.Append( _L( "_nokia_vpi.tmp" ) );
+
+#ifdef _DEBUG
+ if (iOutputVideoType == EVideoAVCProfileBaseline)
+ VPASSERT(iImageAvcEdit);
+#endif
+
+ iImageComposer = CMP4Composer::NewL(iCurrentMovieName, (CParser::TVideoFormat)iOutputVideoType,
+ CParser::EAudioFormatNone,
+ iImageAvcEdit);
+
+ CComposer::TStreamParameters innerStreamParameters;
+ /* there will be no video clips initially, so initialize to default parameters of movie */
+ TSize innerRes =(TSize)iVideoClip->Info()->Resolution(); /* resolution from generator */
+ innerStreamParameters.iVideoWidth = innerRes.iWidth; /* iVideoParameters.iWidth */
+ innerStreamParameters.iVideoHeight = innerRes.iHeight; /* iVideoParameters.iHeight */;
+ /* width and height are initialised to the proper values from the clip */
+ innerStreamParameters.iStreamBitrate = 25000 /* iStreamBitrate */;
+
+ /* set the duration of the video clip */
+ TTimeIntervalMicroSeconds iTempVideoLength= TTimeIntervalMicroSeconds(iVideoClip->Info()->Duration());
+ TInt64 iTimeInMicro = (iTempVideoLength.Int64()/1000);
+ innerStreamParameters.iVideoLength= I64INT(iTimeInMicro); /* set the video length properly */
+ innerStreamParameters.iStreamLength= I64INT(iTimeInMicro);
+ innerStreamParameters.iAudioLength = 0;
+ innerStreamParameters.iAudioFormat = (CComposer::TAudioFormat)0;
+ CVedMovieImp* tempm = (iMovie);
+
+ if(iOutputVideoType == EVideoMPEG4)
+ {
+ /* initialize to default constants for generated clips in case of MPEG-4 */
+ innerStreamParameters.iVideoFormat = (CComposer::TVideoFormat) CComposer::EVideoFormatMPEG4;
+ TVedTranscodeFactor tempFact;
+ tempFact.iStreamType = EVedVideoBitstreamModeMPEG4Regular;
+ tempFact.iTRes = 29;
+ CVedVideoClip* currentClip = tempm->VideoClip(iVideoClipNumber);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+ currentInfo->SetTranscodeFactor(tempFact); /* set to default values, as initialized above */
+ }
+ else if ( (iOutputVideoType == EVideoH263Profile0Level10) ||
+ (iOutputVideoType == EVideoH263Profile0Level45) )
+ {
+
+ innerStreamParameters.iVideoFormat = (CComposer::TVideoFormat)iOutputVideoType;
+ /* initialize to default constants for generated clips in case of H.263 */
+ TVedTranscodeFactor tempFact;
+ tempFact.iStreamType = EVedVideoBitstreamModeH263;
+ tempFact.iTRes = 0;
+ CVedVideoClip* currentClip = tempm->VideoClip(iVideoClipNumber);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+ currentInfo->SetTranscodeFactor(tempFact); /* set to default values, as initialized above */
+ }
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ else if (iOutputVideoType == EVideoAVCProfileBaseline)
+ {
+ /* initialize to default constants for generated clips in case of AVC */
+ innerStreamParameters.iVideoFormat = (CComposer::TVideoFormat) CComposer::EVideoFormatAVCProfileBaseline;
+ TVedTranscodeFactor tempFact;
+ tempFact.iStreamType = EVedVideoBitstreamModeAVC;
+ tempFact.iTRes = 30;
+ CVedVideoClip* currentClip = tempm->VideoClip(iVideoClipNumber);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+ currentInfo->SetTranscodeFactor(tempFact); /* set to default values, as initialized above */
+ }
+#endif
+ else
+ User::Leave(KErrNotSupported);
+
+
+ if(iAllGeneratedClips == 1)
+ {
+ innerStreamParameters.iVideoWidth = iVideoParameters.iWidth;
+ innerStreamParameters.iVideoHeight = iVideoParameters.iHeight;
+ }
+ innerStreamParameters.iCanSeek = ETrue;
+ innerStreamParameters.iHaveVideo = ETrue;
+ innerStreamParameters.iHaveAudio =EFalse;
+ innerStreamParameters.iAudioFramesInSample =0;
+ innerStreamParameters.iAudioTimeScale =KAMRAudioTimeScale; /* 8000 */
+ innerStreamParameters.iVideoTimeScale =iImageVideoTimeScale;
+ iImageComposer->ComposeHeaderL(innerStreamParameters,iImageVideoTimeScale /*iOutputVideoTimeScale*/,
+ iOutputAudioTimeScale, iAudioFramesInSample);
+
+ if(!iVideoEncoder)
+ {
+ /* It should never come here as iVideoEncoder is created before in hand */
+ PRINT(_L("ERROR I VIDEOENCODER DOES NOT EXIST"));
+ return 1; /* Indicating error */
+ }
+ else
+ {
+ //iVideoEncoder->Start(); /* make sure it is started only once */
+ }
+
+ TInt erInitialize = CreateImage3GPFilesL(aCreateMode);
+ iTotalImagesProcessed++;
+ return erInitialize;
+ }
+ else if (aCreateMode == EVideoEncodeFrame && iImageEncodeProcFinished == 0)
+ {
+ /* for encoding, you will read from file, so increment the number of images processed */
+ TInt er = CreateImage3GPFilesL(aCreateMode);
+ /* before incrementing the number of images processed, check if it has actually been encoded */
+
+ iTotalImagesProcessed++;
+
+ return er;
+ }
+ else if(aCreateMode == EVideoWriteFrameToFile && iImageEncodeProcFinished == 0)
+ {
+ // a frame has been encoded, write it to output 3gp buffer
+ TInt er2 = CreateImage3GPFilesL(aCreateMode);
+ return er2;
+ }
+ else if(aCreateMode == EVideoWriteFrameToFile && iImageEncodeProcFinished == 1)
+ {
+ return KErrGeneral; /* This should not happen */
+ }
+ else
+ {
+ /* This should not happen */
+ return KErrGeneral;
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::EncodeImageFrameL
+// Encodes raw frames for 3gp generated clips
+// The frame is in buffer pointed to by iReadImageDes.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::EncodeImageFrameL()
+{
+
+ if (iProcessingCancelled)
+ return KErrNone;
+
+ iVideoEncoder->Stop();
+
+ TTimeIntervalMicroSeconds inMSeconds = TTimeIntervalMicroSeconds(iVideoClip->Info()->Generator()->VideoFrameStartTime(iTotalImagesProcessed));
+
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ iVideoEncoder->EncodeFrameL(iReadImageDes, iStatus,inMSeconds);
+
+ iTotalImagesProcessed++; /* Now we have encoded, and previously we had not, so increment now */
+ iImageEncodedFlag = 1;
+ iEncodeInProgress = 1; /* set to indicate encoding in progress */
+
+ return KErrNone;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ProcessImageSetsL
+// Decides whether to encode or request for a frame from generator,
+// and in what mode to call the CreateImageFiles function
+// The encoding is done calling the GetFrame, so it goes through the frame generator
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::DoImageSetProcessL()
+{
+
+ if (iProcessingCancelled)
+ return;
+
+ // we come here from RunL
+
+ if(iImageEncodedFlag == 0 && iImageEncodeProcFinished == 0)
+ {
+ // Starting to process an image => issue GetFrame() -request
+
+ if(iFirstTimeProcessing == 0)
+ {
+ // this will be known from a bit or flag from the video clip
+ iFirstTimeProcessing = 1; // this indicates that this is the first time we are getting info about this video clip
+ iTotalImagesProcessed = 0;
+ iNumOfImages = (TInt)iVideoClip->Info()->VideoFrameCount();
+ }
+ TSize tempres = iMovie->Resolution();
+ if(iTotalImagesProcessed < iNumOfImages)
+ {
+ iGetFrameInProgress = 1; // indicates that the GetFrame was called and will be in progress
+ iVideoClip->Info()->Generator()->GetFrameL(*this, /*0*/ iTotalImagesProcessed,&tempres, EColor4K, EFalse, 1);
+ }
+ else
+ {
+ // It should never come here though
+ iImageClipCreated = 1;
+ }
+ }
+ else if(iImageEncodedFlag == 1 && iImageEncodeProcFinished == 0)
+ {
+ // image has been encoded
+
+ // tell the function to compose and return
+ iEncodeInProgress = 0;
+ iGetFrameInProgress = 0; // finished getting the frame, so if there's a cancel, no need to delete bitmap etc
+ ProcessImageSetsL(EVideoWriteFrameToFile); // composing of VedVideoClipgenerator, though its not used inside
+ if(iNumOfImages == iTotalImagesProcessed) /// if all images are over
+ {
+ iImageClipCreated = 1;
+ iImageEncodeProcFinished = 1; // finished creating the image 3GP file, so go ahead */
+ iImageComposer->Close();
+
+ delete iImageComposer;
+ iImageComposer = 0;
+
+ if(iParser)
+ {
+ delete iParser;
+ iParser = 0;
+ }
+
+ /* set constant file name used as buffer */
+ iClipFileName = TPtrC(KTempFilePath);
+ iClipFileName.Append( _L("Im_nokia_vpi.tmp") );
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+
+ if (iVideoEncoder)
+ {
+ iVideoEncoder->Stop();
+ delete iVideoEncoder;
+ iVideoEncoder = 0;
+ }
+
+ InitializeGeneratedClipL();
+ /* reset the number of images for the next image set */
+ iImageEncodedFlag = 0;
+
+ if(!IsActive())
+ {
+ SetActive(); // wait till the video encoder finishes initialising
+ iStatus = KRequestPending;
+ }
+ User::Free(iYuvImageBuf);
+ iYuvImageBuf = 0;
+ }
+ else
+ {
+ // request for a new frame
+
+ User::Free(iYuvImageBuf);
+ iYuvImageBuf = 0;
+ TSize tempres = iMovie->Resolution();
+ iGetFrameInProgress = 1;
+ iVideoClip->Info()->Generator()->GetFrameL(*this,iTotalImagesProcessed,&tempres,EColor4K,EFalse,1);
+ }
+ }
+}
+
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::Reset
+// Resets the processor for processing a new movie
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ResetL()
+{
+
+ // delete clip structures
+ DeleteClipStructures();
+
+ // delete video processing modules
+ iEncoderInitPending = EFalse;
+ iState = EStatePreparing;
+ DoCloseVideoL();
+ iState = EStateIdle;
+
+ VPASSERT(!iEncoderInitPending);
+ VPASSERT(!iVideoEncoder);
+
+ if (iComposer)
+ {
+ delete iComposer;
+ iComposer = 0;
+ }
+
+ if(iImageComposer)
+ {
+ delete iImageComposer;
+ iImageComposer=0;
+ }
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+
+ if (iYuvImageBuf)
+ {
+ User::Free(iYuvImageBuf);
+ iYuvImageBuf=0;
+ }
+
+ // for transition effect
+ if ( iFsConnected )
+ {
+ CloseTransitionInfoL();
+ iFs.Close();
+ iFsConnected = EFalse;
+ }
+
+ iDataFormat = EDataAutoDetect;
+ iStreamBitrate = 0;
+ iNumDemuxChannels = 0;
+ iOutputNumberOfFrames = 0;
+ iVideoType = EVideoH263Profile0Level10;
+ iAudioType = EAudioAMR;
+ iFirstFrameOfClip = EFalse;
+ iFirstFrameFlagSet = EFalse;
+
+ iFirstClipUsesEncoder = EFalse;
+ iMpeg4ModeTranscoded = EFalse;
+
+ iOutputVideoTimeScale = KVideoTimeScale;
+ iOutputAudioTimeScale = KAMRAudioTimeScale;
+ iOutputVideoType = EVideoNone;
+ iOutputAudioType = EAudioAMR;
+
+ iProcessingCancelled = EFalse;
+
+ iStartTransitionEffect = EVedStartTransitionEffectNone;
+ iMiddleTransitionEffect = EVedMiddleTransitionEffectNone;
+ iPreviousMiddleTransitionEffect = EVedMiddleTransitionEffectNone;
+ iEndTransitionEffect = EVedEndTransitionEffectNone;
+ iWriting1stColorTransitionFrame = EFalse;
+ i1stColorTransitionFrameTS = 0;
+
+ iApplySlowMotion = ETrue;
+ iCurrentVideoTimeInTicks = 0.0;
+ iInitialClipStartTimeStamp = 0;
+ iStartingProcessing = EFalse;
+ iFramesProcessed = 0;
+ iProgress = 0;
+ iGeneratedProcessed = 0;
+ iAudioProcessingCompleted = EFalse;
+ iEncodingBlackFrames = EFalse;
+
+ iTotalDurationInSample = 0;
+ iAudioProcessingCancelled = EFalse;
+ iWaitSchedulerStarted = EFalse;
+
+ iCurrentMovieName.Zero();
+ iAudioClipWritten = 0;
+ iVideoClipWritten = 0;
+ iDiskFull = EFalse;
+ iAudioFrameNumber = 0;
+ iVideoFrameNumber = 0;
+ iFrameBuffered = EFalse;
+ iVideoIntraFrameNumber = 0;
+ iVideoClipNumber=0;
+ iStartFrameIndex = 0;
+ iVideoClip=0;
+ iMovie=0;
+ iSpeed = KMaxVideoSpeed;
+ iColorEffect = EVedColorEffectNone;
+ iNumberOfVideoClips=0;
+ iEncoderBuffer = 0;
+ iEncodePending = 0;
+ iVideoClipDuration = 0;
+ iLeftOverDuration = 0;
+ iTimeStamp = 0;
+
+ iThumbnailInProgress=EFalse;
+ iTotalMovieDuration = 0;
+ iFramesProcessed=0;
+ iStartCutTime = TTimeIntervalMicroSeconds(0);
+ iEndCutTime = TTimeIntervalMicroSeconds(0);
+
+ iTr.iTrPrevNew = -1;
+ iTr.iTrPrevOrig = -1;
+
+ iAudioFramesInSample = KVedAudioFramesInSample;
+ iAudioFramesInBuffer = 0;
+ iOutAudioBuffer=0;
+ iNumberOfAudioClipsCreated = 0;
+ iCurrentAudioTimeInMs = 0;
+ iTotalAudioTimeWrittenMs = 0;
+ iNumberOfAudioClips=0;
+ iAudioClipNumber=0;
+ iTimeStampListScaled = EFalse;
+
+ iCurrentVideoSize = 0;
+ iCurrentAudioSize = 0;
+ iMovieSizeLimitExceeded = EFalse;
+
+ iAllVideoProcessed = EFalse;
+
+ // We are now properly initialized
+ iState = EStateIdle;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CancelProcessingL
+// Stops processing a movie
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::CancelProcessingL()
+{
+
+ PRINT((_L("CancelProcessingL begin, iEncoderInitPending %d, iEncodePending %d, iEncodeInProgress %d"),
+ iEncoderInitPending, iEncodePending, iEncodeInProgress ));
+
+#ifdef _DEBUG
+ if (iVideoEncoder)
+ PRINT((_L("CancelProcessingL() - iEncodePending in encoder %d"), iVideoEncoder->IsEncodePending()));
+#endif
+
+ if (iProcessingCancelled)
+ {
+ PRINT((_L("CancelProcessingL() - Already cancelled!")));
+
+ if (iMonitor)
+ iMonitor->ProcessingCancelled();
+
+ return;
+ }
+
+ iProcessingCancelled = ETrue;
+
+ if (iDemux)
+ iDemux->Stop();
+
+ if (iVideoProcessor)
+ iVideoProcessor->Stop();
+
+ if (iAudioProcessor)
+ iAudioProcessor->StopL();
+
+ // delete all objects except status monitor
+ DoCloseVideoL();
+
+ if ( iVideoEncoder && iVideoEncoder->IsEncodePending() == 0 &&
+ (iEncodePending || iEncodeInProgress) )
+ {
+ // encoder has completed encoding request, but scheduler has
+ // not called RunL() yet. Reset flags so that the request will
+ // be handled as init complete in RunL
+ PRINT((_L("CancelProcessingL() - resetting encoding flags")));
+ iEncoderInitPending = ETrue;
+ iEncodePending = iEncodeInProgress = 0;
+ }
+
+ // close the rest
+
+ // for transition effect
+ if ( iFsConnected )
+ {
+ CloseTransitionInfoL();
+ iFs.Close();
+ iFsConnected = EFalse;
+ }
+
+ if(iGetFrameInProgress == 1)
+ {
+ //VPASSERT(iEncodeInProgress == 0);
+ iGetFrameInProgress = 0;
+
+ if(iVideoClip->Info()->Class() == EVedVideoClipClassGenerated)
+ {
+ iVideoClip->Info()->Generator()->CancelFrame();
+ }
+ }
+
+ if (iComposer)
+ {
+ iComposer->Close(); // creates the output file
+ delete iComposer;
+ iComposer = 0;
+ }
+
+ if(iImageComposer)
+ {
+ delete iImageComposer;
+ iImageComposer=0;
+ }
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+
+
+ DeleteClipStructures();
+
+ if (!iEncoderInitPending)
+ {
+
+ PRINT((_L("CMovieProcessorImpl::CancelProcessingL - calling cancelled callback")));
+ // if StartMovieL() has not been called at this point,
+ // there is no status monitor or observer to call
+ if (iMonitor)
+ iMonitor->ProcessingCancelled();
+
+ iState = EStateIdle;
+ }
+
+ PRINT((_L("CMovieProcessorImpl::CancelProcessingL end")))
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetClipPropertiesL
+// Retrieves parameters for a clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::GetClipPropertiesL(const TDesC& aFileName,
+ RFile* aFileHandle,
+ TVedVideoFormat& aFormat,
+ TVedVideoType& aVideoType,
+ TSize& aResolution,
+ TVedAudioType& aAudioType,
+ TTimeIntervalMicroSeconds& aDuration,
+ TInt& aVideoFrameCount,
+ TInt& aSamplingRate,
+ TVedAudioChannelMode& aChannelMode)
+{
+
+ PRINT((_L("CMovieProcessorImpl::GetClipPropertiesL() begin")))
+
+ TInt error = KErrNone;
+ if (!aFileHandle)
+ {
+ // Check that 3gp file exists.
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+
+ RFile file;
+ error = file.Open(fs, aFileName, EFileShareReadersOnly | EFileStream | EFileRead);
+ if ( error != KErrNone )
+ {
+ error = file.Open(fs, aFileName, EFileShareAny | EFileStream | EFileRead);
+ }
+ if (error == KErrNone)
+ {
+ file.Close();
+ }
+ fs.Close();
+ User::LeaveIfError(error);
+
+ // get filename
+ iClipFileName = aFileName;
+ iClipFileHandle = NULL;
+ }
+ else
+ {
+ iClipFileHandle = aFileHandle;
+ iClipFileName.Zero();
+ }
+
+ CParser::TStreamParameters iStreamParams;
+
+ // parse header
+ TRAP(error, ParseHeaderOnlyL(iStreamParams, iClipFileName, iClipFileHandle));
+
+ if (error != KErrNone && error != KErrNotSupported)
+ User::Leave(error);
+
+ /* pass back clip properties */
+
+ // video format (file format actually)
+ if (iStreamParams.iFileFormat == CParser::EFileFormat3GP)
+ aFormat = EVedVideoFormat3GPP;
+ else if (iStreamParams.iFileFormat == CParser::EFileFormatMP4)
+ aFormat = EVedVideoFormatMP4;
+ else
+ aFormat = EVedVideoFormatUnrecognized;
+
+ // video type
+ if(iStreamParams.iVideoFormat == CParser::EVideoFormatNone)
+ aVideoType = EVedVideoTypeNoVideo;
+ else if (iStreamParams.iVideoFormat == CParser::EVideoFormatH263Profile0Level10)
+ aVideoType = EVedVideoTypeH263Profile0Level10;
+ else if (iStreamParams.iVideoFormat == CParser::EVideoFormatH263Profile0Level45)
+ aVideoType = EVedVideoTypeH263Profile0Level45;
+ else if(iStreamParams.iVideoFormat == CParser::EVideoFormatMPEG4)
+ aVideoType = EVedVideoTypeMPEG4SimpleProfile;
+ else if(iStreamParams.iVideoFormat == CParser::EVideoFormatAVCProfileBaseline)
+ aVideoType = EVedVideoTypeAVCBaselineProfile;
+ else
+ aVideoType = EVedVideoTypeUnrecognized;
+
+ // audio type
+ if(!iStreamParams.iHaveAudio/*iStreamParams.iAudioFormat == CParser::EAudioFormatNone*/)
+ aAudioType=EVedAudioTypeNoAudio;
+ else if(iStreamParams.iAudioFormat == CParser::EAudioFormatAMR)
+ aAudioType=EVedAudioTypeAMR;
+ else if (iStreamParams.iAudioFormat == CParser::EAudioFormatAAC)
+ aAudioType=EVedAudioTypeAAC_LC; // what about EVedAudioTypeAAC_LTP ???
+ else
+ aAudioType=EVedAudioTypeUnrecognized;
+
+ // Dummy values, update when AAC support is there
+ aSamplingRate = KVedAudioSamplingRate8k;
+ aChannelMode = EVedAudioChannelModeSingleChannel;
+
+ // resolution
+ aResolution.iWidth = iStreamParams.iVideoWidth;
+ aResolution.iHeight = iStreamParams.iVideoHeight;
+
+ // common
+ TUint duration = (iStreamParams.iVideoLength > iStreamParams.iAudioLength ?
+ iStreamParams.iVideoLength : iStreamParams.iAudioLength);
+ aDuration = TTimeIntervalMicroSeconds( TInt64(duration) * TInt64(1000) );
+
+ // get total number of video frames
+ aVideoFrameCount = iParser->GetNumberOfVideoFrames();
+
+ /***************IF Audio Type is AAC get the audio properties************************/
+
+ if(iStreamParams.iAudioFormat == CParser::EAudioFormatAAC)
+ {
+ //temporarily initialize iOutputAudioType and iAudioType as AudioProcessor uses it
+ iOutputAudioType = EAudioAAC;
+ iAudioType = EAudioAAC;
+ }
+
+ PRINT((_L("CMovieProcessorImpl::GetClipPropertiesL() end")))
+}
+
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GenerateVideoFrameInfoArray
+// Retrieves frames parameters for a clip to array
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::GenerateVideoFrameInfoArrayL(const TDesC& aFileName, RFile* aFileHandle,
+ TVedVideoFrameInfo*& aVideoFrameInfoArray)
+{
+
+ PRINT((_L("CMovieProcessorImpl::GenerateVideoFrameInfoArray() begin")))
+
+ TInt error;
+
+ if (!aFileHandle)
+ {
+ // Check that 3gp file exists.
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+
+ RFile file;
+ error = file.Open(fs, aFileName, EFileShareReadersOnly | EFileStream | EFileRead);
+ if ( error != KErrNone )
+ {
+ error = file.Open(fs, aFileName, EFileShareAny | EFileStream | EFileRead);
+ }
+ if (error == KErrNone)
+ {
+ file.Close();
+ }
+ fs.Close();
+ User::LeaveIfError(error);
+ }
+
+ // parse clip header
+ CParser::TStreamParameters streamParams;
+
+ // get filename
+ if (aFileHandle)
+ {
+ iClipFileName.Zero();
+ iClipFileHandle = aFileHandle;
+ }
+ else
+ {
+ iClipFileHandle = NULL;
+ iClipFileName = aFileName;
+ }
+
+ // parse header
+ TRAP(error, ParseHeaderOnlyL(streamParams, iClipFileName, iClipFileHandle));
+
+ if (error != KErrNone && error != KErrNotSupported)
+ {
+ User::Leave( error );
+ }
+
+ // video type
+ TVedVideoType videoType = EVedVideoTypeNoVideo;
+ if(streamParams.iVideoFormat == CParser::EVideoFormatNone)
+ videoType = EVedVideoTypeNoVideo;
+ else if(streamParams.iVideoFormat == CParser::EVideoFormatH263Profile0Level10)
+ videoType = EVedVideoTypeH263Profile0Level10;
+ else if(streamParams.iVideoFormat == CParser::EVideoFormatH263Profile0Level45)
+ videoType = EVedVideoTypeH263Profile0Level45;
+ else if(streamParams.iVideoFormat == CParser::EVideoFormatMPEG4)
+ videoType = EVedVideoTypeMPEG4SimpleProfile;
+ else if(streamParams.iVideoFormat == CParser::EVideoFormatAVCProfileBaseline)
+ videoType = EVedVideoTypeAVCBaselineProfile;
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // frame parameters
+ if( (videoType == EVedVideoTypeH263Profile0Level10) ||
+ (videoType == EVedVideoTypeH263Profile0Level45) ||
+ (videoType == EVedVideoTypeMPEG4SimpleProfile) ||
+ (videoType == EVedVideoTypeAVCBaselineProfile) )
+ {
+ TInt frameCount = 0;
+ FillVideoFrameInfoArrayL(frameCount, (TVedVideoFrameInfo*&)aVideoFrameInfoArray);
+ }
+
+ PRINT((_L("CMovieProcessorImpl::GenerateVideoFrameInfoArray() end")))
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FillVideoFrameInfoArray
+// Fills an array containing video frame parameters: size, start time & type
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+void CMovieProcessorImpl::FillVideoFrameInfoArrayL(TInt& aVideoFrameCount,
+ TVedVideoFrameInfo*& aVideoFrameInfoArray)
+{
+
+ PRINT((_L("CMovieProcessorImpl::FillVideoFrameInfoArrayL() begin")))
+
+ // get total number of video frames
+ aVideoFrameCount = iParser->GetNumberOfVideoFrames();
+ VPASSERT(aVideoFrameCount);
+ // create memory for frame parameters - DO NOT delete it in MediaProcessorImpl
+ if(aVideoFrameInfoArray)
+ {
+ delete aVideoFrameInfoArray;
+ aVideoFrameInfoArray=0;
+ }
+
+ // get individual frame parameters
+ aVideoFrameInfoArray = (TVedVideoFrameInfo*)User::AllocL(aVideoFrameCount * sizeof(class TVedVideoFrameInfo));
+
+ TFrameInfoParameters* frameInfoArray = (TFrameInfoParameters*)User::AllocZL((aVideoFrameCount) * sizeof(struct TFrameInfoParameters));
+
+ TInt i;
+ // Get all the frame parameters using the new function
+ CMP4Parser* parser = (CMP4Parser*)iParser;
+ TInt startIndex =0;
+ TInt err = parser->GetVideoFrameProperties(frameInfoArray,startIndex,aVideoFrameCount);
+ if(err !=0)
+ User::Leave(KErrAbort);
+
+ for(i=0; i<aVideoFrameCount; i++)
+ {
+ aVideoFrameInfoArray[i].iSize = (TInt)frameInfoArray[i].iSize;
+ aVideoFrameInfoArray[i].iStartTime = (TInt)frameInfoArray[i].iStartTime;
+ if(frameInfoArray[i].iType)
+ {
+ PRINT((_L("CMovieProcessorImpl::FillVideoFrameInfoArrayL() iType of %d nonzero, time %d"), i, aVideoFrameInfoArray[i].iStartTime))
+ aVideoFrameInfoArray[i].iFlags = 1;
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::FillVideoFrameInfoArrayL() iType of %d zero, time %d"), i, aVideoFrameInfoArray[i].iStartTime))
+ aVideoFrameInfoArray[i].iFlags = 0;
+ }
+ }
+ User::Free(frameInfoArray);
+ frameInfoArray=0;
+
+ PRINT((_L("CMovieProcessorImpl::FillVideoFrameInfoArrayL() end")))
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FillFrameParameters
+// Fills an internal array containing parameters for each video frame :
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::FillFrameParametersL(TInt aCurrentFrameIndex)
+{
+ PRINT((_L("CMovieProcessorImpl::FillFrameParameters() begin, current index %d"),aCurrentFrameIndex))
+
+ // get total number of video frames
+ TInt numberOfFrames = iParser->GetNumberOfFrames();
+ TInt frameNumber = 0;
+
+ // get start frame index in the input clip
+ iStartFrameIndex = iParser->GetStartFrameIndex();
+
+ TInt cutOutTime = 0;
+ if (!iThumbnailInProgress)
+ cutOutTime = I64INT( iVideoClip->CutOutTime().Int64() / TInt64(1000) );
+
+ TFrameInfoParameters* frameInfoArray =
+ (TFrameInfoParameters*)User::AllocZL((numberOfFrames) * sizeof(struct TFrameInfoParameters));
+
+ CleanupStack::PushL(frameInfoArray);
+
+ // get info array from parser
+ CMP4Parser* parser = (CMP4Parser*)iParser;
+ TInt error = parser->GetVideoFrameProperties(frameInfoArray, iStartFrameIndex, numberOfFrames);
+ if (error != 0)
+ User::Leave(KErrAbort);
+
+ while ( frameNumber < numberOfFrames )
+ {
+ iFrameParameters[aCurrentFrameIndex].iTimeStamp =
+ GetVideoTimeInTicksFromMs( TInt64(frameInfoArray[frameNumber].iStartTime), EFalse );
+ iFrameParameters[aCurrentFrameIndex].iType = TUint8( frameInfoArray[frameNumber].iType );
+
+ if (!iThumbnailInProgress && frameInfoArray[frameNumber].iStartTime > cutOutTime)
+ {
+ break;
+ }
+
+ frameNumber++;
+ aCurrentFrameIndex++;
+ }
+
+ CleanupStack::PopAndDestroy(frameInfoArray);
+
+ PRINT((_L("CMovieProcessorImpl::FillFrameParameters() end")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::IncProgressBar
+// Report progress to observer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//-
+void CMovieProcessorImpl::IncProgressBar()
+{
+ VPASSERT(iTotalMovieDuration > 0);
+
+ TInt64 msProcessed = iGeneratedProcessed + iTotalAudioTimeWrittenMs +
+ GetVideoTimeInMsFromTicks(iCurrentVideoTimeInTicks, ETrue);
+
+ TInt percentage = TInt( ( (I64REAL(msProcessed) / I64REAL(iTotalMovieDuration)) * 100.0) + 0.5 );
+
+ //VPASSERT( percentage <= 100 );
+
+ if (percentage > iProgress && percentage <= 100)
+ {
+ iProgress = percentage;
+ iMonitor->Progress(iProgress);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieSizeEstimateL
+// Calculates an estimate for resulting movie size
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetMovieSizeEstimateL(const CVedMovie* aMovie)
+{
+ TInt fileSize=0;
+ iSizeEstimate->GetMovieSizeEstimateL(aMovie, (TInt&)fileSize);
+ return fileSize;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieSizeEstimateForMMSL
+// Calculates file size estimate for MMS use
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetMovieSizeEstimateForMMSL(const CVedMovie* aMovie,
+ TInt aTargetSize,
+ TTimeIntervalMicroSeconds aStartTime,
+ TTimeIntervalMicroSeconds& aEndTime)
+{
+ return iSizeEstimate->GetMovieSizeEstimateForMMSL(aMovie, aTargetSize, aStartTime, aEndTime);
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::StartThumbL
+// Initiates thumbnail extraction from clip (full resolution raw is reutrned)
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::StartThumbL(const TDesC& aFileName,
+ RFile* aFileHandle,
+ TInt aIndex,
+ TSize aResolution,
+ TDisplayMode aDisplayMode,
+ TBool aEnhance)
+{
+
+ PRINT((_L("CMovieProcessorImpl::StartThumbL() begin, aIndex = %d, enhance = %d"), aIndex, aEnhance))
+
+ if (!aFileHandle)
+ {
+ //Check that 3gp file exists.
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ RFile file;
+ TInt error = file.Open(fs, aFileName, EFileShareReadersOnly | EFileStream | EFileRead);
+ if ( error != KErrNone )
+ {
+ error = file.Open(fs, aFileName, EFileShareAny | EFileStream | EFileRead);
+ }
+ if (error == KErrNone)
+ {
+ file.Close();
+ }
+ fs.Close();
+ User::LeaveIfError(error);
+ }
+
+ // get thumbnail parameters
+ if (aFileHandle)
+ {
+ iClipFileName.Zero();
+ iClipFileHandle = aFileHandle;
+ }
+ else
+ {
+ iClipFileHandle = NULL;
+ iClipFileName = aFileName;
+ }
+
+ iOutputThumbResolution.SetSize(aResolution.iWidth, aResolution.iHeight);
+ iThumbIndex = aIndex;
+ iThumbDisplayMode = aDisplayMode;
+ iThumbEnhance = aEnhance;
+
+ iThumbnailInProgress = ETrue;
+
+ // initialization
+ InitializeClipStructuresL();
+
+ InitializeClipL(); // opens the file & parses header
+
+ // update number of frames
+ SetOutputNumberOfFrames(iParser->iOutputNumberOfFrames);
+
+ PRINT((_L("CMovieProcessorImpl::StartThumbL() end")))
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ProcessThumbL
+// Generates thumbnail from clip (actually, full resolution raw is returned)
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ProcessThumbL(TRequestStatus &aStatus, TVedTranscodeFactor* aFactor)
+{
+
+ PRINT((_L("CMovieProcessorImpl::ProcessThumbL() begin")))
+
+ iState = EStateProcessing;
+ iThumbnailRequestStatus = &aStatus;
+
+ // seek to the last intra frame before desired frame
+ TTimeIntervalMicroSeconds startTime(0);
+ if ( iThumbIndex > 0 )
+ {
+ TInt time = 0;
+ TUint inMs = TUint( iParser->GetVideoFrameStartTime(iThumbIndex, &time) );
+ TInt64 inMicroS = TInt64( inMs ) * TInt64( 1000 );
+ startTime = TTimeIntervalMicroSeconds( inMicroS );
+ }
+
+ // iOutputNumberOFrames contains the total amount of frames in clip
+ // without cutting
+ SetOutputNumberOfFrames(iParser->iOutputNumberOfFrames);
+
+ TInt error = iParser->SeekOptimalIntraFrame(startTime, iThumbIndex, ETrue);
+ if (error != KErrNone)
+ {
+ iThumbnailRequestStatus = 0;
+ User::Leave(KErrGeneral);
+ }
+ iStartFrameIndex = iParser->GetStartFrameIndex();
+ VPASSERT(iStartFrameIndex >= 0);
+
+ error = iVideoProcessor->ProcessThumb(this, iThumbIndex, iStartFrameIndex, aFactor);
+ if (error != KErrNone)
+ {
+ iThumbnailRequestStatus = 0;
+ User::Leave(error);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::NotifyThumbnailReady
+// Called by thumbnail generator when thumbnail is ready
+// for retrieval
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::NotifyThumbnailReady(TInt aError)
+{
+
+ PRINT((_L("CMovieProcessorImpl::NotifyThumbnailReady() begin")))
+
+ if (HandleThumbnailError(aError))
+ return;
+
+ // get YUV thumb
+ iVideoProcessor->FetchThumb(&iYuvBuf);
+
+ // check validity of thumbnail and associated operation
+ if(iThumbEnhance) // for saving to file
+ {
+ if(iThumbDisplayMode == ENone) // if no preference
+ iThumbDisplayMode = EColor16M; // 24-bit color image for enhancement
+ else if(iThumbDisplayMode != EColor16M) // invalid combination
+ {
+ HandleThumbnailError(KErrNotSupported);
+ return;
+ }
+ }
+ else // for screen display
+ {
+ if(iThumbDisplayMode == ENone) // if no preference
+ iThumbDisplayMode = EColor64K; // 16-bit image for some products
+ }
+
+ TInt bytesPerPixel = 0;
+ // determine proper bit depth for the bitmap
+ if(iThumbDisplayMode == EColor16M)
+ bytesPerPixel = 3; // 24-bit rgb takes 3 bytes, stored as bbbbbbbb gggggggg rrrrrrrr
+ else if(iThumbDisplayMode == EColor64K || iThumbDisplayMode == EColor4K)
+ bytesPerPixel = 2; // 12-bit rgb takes 2 bytes, stored as ggggbbbb xxxxrrrr
+ else
+ {
+ HandleThumbnailError(KErrNotSupported);
+ return; // support for 12-, 16- and 24-bit color images only
+ }
+
+ TInt error;
+ if ( !iRgbBuf )
+ {
+ TSize inputFrameResolution(iParser->iStreamParameters.iVideoWidth,iParser->iStreamParameters.iVideoHeight);
+
+ // rgb specs
+ TUint thumbLength = inputFrameResolution.iWidth * inputFrameResolution.iHeight;
+ TUint thumbUVLength = thumbLength>>2;
+
+ VPASSERT(iYuvBuf);
+ // assign yuv pointers
+ TUint8* yBuf = iYuvBuf;
+ TUint8* uBuf = yBuf + thumbLength;
+ TUint8* vBuf = uBuf + thumbUVLength;
+
+ // create output rgb buffer
+ TRAP(error, iRgbBuf = (TUint8*) User::AllocL(thumbLength * bytesPerPixel));
+ if (HandleThumbnailError(error))
+ return;
+
+ TInt scanLineLength;
+
+ // convert yuv to rgb
+ switch (iThumbDisplayMode)
+ {
+
+ case EColor4K:
+ {
+ TInt error;
+ CYuv2Rgb12* yuvConverter = NULL;
+ TRAP(error, yuvConverter = new(ELeave) CYuv2Rgb12);
+ if (HandleThumbnailError(error))
+ return;
+ scanLineLength = inputFrameResolution.iWidth * bytesPerPixel;
+ VPASSERT(yuvConverter);
+ TRAP(error, yuvConverter->ConstructL(inputFrameResolution.iWidth, inputFrameResolution.iHeight, inputFrameResolution.iWidth, inputFrameResolution.iHeight));
+ if (HandleThumbnailError(error))
+ return;
+ yuvConverter->Convert(yBuf, uBuf, vBuf, inputFrameResolution.iWidth, inputFrameResolution.iHeight, iRgbBuf, scanLineLength);
+ delete yuvConverter;
+ yuvConverter=0;
+ }
+ break;
+
+ default:
+ case EColor64K:
+ {
+ TInt error;
+ CYuv2Rgb16* yuvConverter = NULL;
+ TRAP(error, yuvConverter = new(ELeave) CYuv2Rgb16);
+ if (HandleThumbnailError(error))
+ return;
+ scanLineLength = inputFrameResolution.iWidth * bytesPerPixel;
+ VPASSERT(yuvConverter);
+ TRAP(error, yuvConverter->ConstructL(inputFrameResolution.iWidth, inputFrameResolution.iHeight, inputFrameResolution.iWidth, inputFrameResolution.iHeight);)
+ if (HandleThumbnailError(error))
+ return;
+ yuvConverter->Convert(yBuf, uBuf, vBuf, inputFrameResolution.iWidth, inputFrameResolution.iHeight, iRgbBuf, scanLineLength);
+ delete yuvConverter;
+ yuvConverter=0;
+ }
+ break;
+
+ case EColor16M:
+ {
+ TInt error;
+ CYuv2Rgb24* yuvConverter = NULL;
+ TRAP(error, yuvConverter = new(ELeave) CYuv2Rgb24);
+ if (HandleThumbnailError(error))
+ return;
+ scanLineLength = inputFrameResolution.iWidth * bytesPerPixel;
+ VPASSERT(yuvConverter);
+ TRAP(error, yuvConverter->ConstructL(inputFrameResolution.iWidth, inputFrameResolution.iHeight, inputFrameResolution.iWidth, inputFrameResolution.iHeight))
+ if (HandleThumbnailError(error))
+ return;
+ yuvConverter->Convert(yBuf, uBuf, vBuf, inputFrameResolution.iWidth, inputFrameResolution.iHeight, iRgbBuf, scanLineLength);
+ delete yuvConverter;
+ yuvConverter=0;
+ }
+ break;
+ }
+ }
+
+ //CFbsBitmap* iOutBitmap = 0;
+
+ if(!iThumbEnhance)
+ {
+ const TSize inputFrameResolution(iParser->iStreamParameters.iVideoWidth,iParser->iStreamParameters.iVideoHeight);
+
+ /* Pre-calculate pixel indices for horizontal scaling. */
+ // inputFrameResolution is the resolution of the image read from video clip.
+ // iOutputThumbResolution is the final resolution desired by the caller.
+
+ const TInt xIncrement = inputFrameResolution.iWidth * iOutputThumbResolution.iWidth;
+ const TInt xBoundary = iOutputThumbResolution.iWidth * iOutputThumbResolution.iWidth;
+
+ TInt* xIndices = 0;
+ TRAPD(xIndicesErr, xIndices = new (ELeave) TInt[iOutputThumbResolution.iWidth]);
+ if (xIndicesErr == KErrNone)
+ {
+ TInt xDecision = xIncrement / bytesPerPixel;
+ TInt sourceIndex = 0;
+ for (TInt x = 0; x < iOutputThumbResolution.iWidth; x++)
+ {
+ while (xDecision > xBoundary)
+ {
+ xDecision -= xBoundary;
+ sourceIndex += bytesPerPixel;
+ }
+
+ xIndices[x] = sourceIndex;
+ xDecision += xIncrement;
+ }
+ }
+ else
+ {
+ HandleThumbnailError(xIndicesErr);
+ return;
+ }
+
+ /* Initialize bitmap. */
+ TRAPD(bitmapErr, iOutBitmap = new (ELeave) CFbsBitmap);
+ if ((xIndicesErr == KErrNone) && (bitmapErr == KErrNone))
+ {
+ bitmapErr = iOutBitmap->Create(iOutputThumbResolution, iThumbDisplayMode /*EColor64K*/);
+ if (bitmapErr == KErrNone)
+ {
+ // Lock the heap to prevent the FBS server from invalidating the address
+ iOutBitmap->LockHeap();
+
+ /* Scale to desired iOutputThumbResolution and copy to bitmap. */
+ TUint8* dataAddress = (TUint8*)iOutBitmap->DataAddress();
+ const TInt yIncrement = inputFrameResolution.iHeight * iOutputThumbResolution.iHeight;
+ const TInt yBoundary = iOutputThumbResolution.iHeight * iOutputThumbResolution.iHeight;
+
+ TInt targetIndex = 0;
+ TInt sourceRowIndex = 0;
+ TInt yDecision = yIncrement / 2;
+ for (TInt y = 0; y < iOutputThumbResolution.iHeight; y++)
+ {
+ while (yDecision > yBoundary)
+ {
+ yDecision -= yBoundary;
+ sourceRowIndex += (inputFrameResolution.iWidth * bytesPerPixel);
+ }
+ yDecision += yIncrement;
+
+ for (TInt x = 0; x < iOutputThumbResolution.iWidth; x++)
+ {
+ for (TInt i = 0; i < bytesPerPixel; ++i)
+ {
+ const TInt firstPixelSourceIndex = sourceRowIndex + xIndices[x] + i;
+ dataAddress[targetIndex] = iRgbBuf[firstPixelSourceIndex];
+ targetIndex++;
+ }
+ }
+ }
+ iOutBitmap->UnlockHeap();
+ }
+ else
+ {
+ delete iOutBitmap; iOutBitmap = 0;
+ HandleThumbnailError(bitmapErr);
+ return;
+ }
+ }
+ else
+ {
+ HandleThumbnailError(bitmapErr);
+ delete[] xIndices; xIndices = 0;
+ return;
+ }
+
+ delete[] xIndices;
+ xIndices = 0;
+ }
+ else // enhance
+ {
+ TInt i,j;
+ // create input bitmap and buffer
+ CFbsBitmap* inBitmap = 0;
+ TRAPD(inBitmapErr, inBitmap = new (ELeave) CFbsBitmap);
+ if( inBitmapErr == KErrNone )
+ {
+ // create bitmaps
+ TSize originalResolution(iParser->iStreamParameters.iVideoWidth, iParser->iStreamParameters.iVideoHeight);
+ inBitmapErr = inBitmap->Create(originalResolution, iThumbDisplayMode/*EColor16M*/);
+
+ if( inBitmapErr == KErrNone )
+ {
+ // fill image from rgb buffer to input bitmap buffer
+ TPtr8 linePtr(0,0);
+ TInt lineLength = inBitmap->ScanLineLength(originalResolution.iWidth, iThumbDisplayMode);
+ for(j=0, i=0; j<originalResolution.iHeight; j++, i+=lineLength)
+ {
+ linePtr.Set(iRgbBuf+i, lineLength, lineLength);
+ inBitmap->SetScanLine((TDes8&)linePtr,j);
+ }
+
+ // create output bitmap
+ TRAPD(outBitmapErr, iOutBitmap = new (ELeave) CFbsBitmap);
+ if( outBitmapErr == KErrNone )
+ {
+ outBitmapErr = iOutBitmap->Create(iOutputThumbResolution, iThumbDisplayMode/*EColor16M*/); // same size as input frame
+
+ if( outBitmapErr == KErrNone )
+ {
+ // post-processing enhancement
+ TRAP(outBitmapErr, EnhanceThumbnailL((const CFbsBitmap*)inBitmap, (CFbsBitmap*)iOutBitmap));
+
+ }
+ else
+ {
+ delete inBitmap; inBitmap = 0;
+ delete iOutBitmap; iOutBitmap = 0;
+ HandleThumbnailError(outBitmapErr);
+ return;
+ }
+ }
+ else
+ {
+ delete inBitmap; inBitmap = 0;
+ HandleThumbnailError(outBitmapErr);
+ return;
+ }
+ }
+ else
+ {
+ delete inBitmap; inBitmap = 0;
+ HandleThumbnailError(inBitmapErr);
+ return;
+ }
+
+ // delete input bitmap
+ delete inBitmap;
+ inBitmap = 0;
+ }
+ else
+ {
+ HandleThumbnailError(inBitmapErr);
+ return;
+ }
+ }
+
+ // return enhanced bitmap
+ //aThumb = outBitmap;
+ //iState = EStateReadyToProcess;
+
+ iYuvBuf = 0;
+ delete iRgbBuf;
+ iRgbBuf = 0;
+
+ VPASSERT(iThumbnailRequestStatus);
+ User::RequestComplete(iThumbnailRequestStatus, KErrNone);
+ iThumbnailRequestStatus = 0;
+
+ PRINT((_L("CMovieProcessorImpl::NotifyThumbnailReady() end")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::HandleThumbnailError
+// Handle error in thumbnail generation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CMovieProcessorImpl::HandleThumbnailError(TInt aError)
+{
+ if (aError != KErrNone)
+ {
+ TInt error = aError;
+
+#ifndef _DEBUG
+ if (error < KErrHardwareNotAvailable)
+ error = KErrGeneral;
+#endif
+
+ VPASSERT(iThumbnailRequestStatus);
+ User::RequestComplete(iThumbnailRequestStatus, error);
+ iThumbnailRequestStatus = 0;
+ return ETrue;
+ }
+ return EFalse;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FetchThumb
+// Returns a pointer to completed thumbnail bitmap
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::FetchThumb(CFbsBitmap*& aThumb)
+{
+ aThumb = iOutBitmap;
+ iOutBitmap = 0;
+
+ iState = EStateReadyToProcess;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::InitializeClipStructuresL
+// Initializes internal structures for movie processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::InitializeClipStructuresL()
+{
+
+ TTimeIntervalMicroSeconds time;
+ TInt i;
+
+ // create memory for structures
+ // VIDEO
+ if(!iVideoClipParameters)
+ {
+ iVideoClipParameters = (struct TVideoClipParameters *)User::AllocL(iNumberOfVideoClips *
+ sizeof(struct TVideoClipParameters));
+ Mem::Fill(iVideoClipParameters, iNumberOfVideoClips*sizeof(TVideoClipParameters), 0);
+ }
+
+ if(!iThumbnailInProgress)
+ {
+ // create audio buffer
+ iOutAudioBuffer = (HBufC8*) HBufC8::NewL(KInitialAudioBufferSize);
+
+ // create video buffer
+ iOutVideoBuffer = (HBufC8*) HBufC8::NewL(KInitialVideoBufferSize);
+
+ CVedMovieImp* movie = (iMovie);
+ // initialize video clip parameters
+ for(i=0; i<iNumberOfVideoClips; i++)
+ {
+ // convert start & end times to milliseconds
+ iVideoClip = movie->VideoClip(i);
+ time = TTimeIntervalMicroSeconds(iVideoClip->StartTime());
+ iVideoClipParameters[i].iStartTime = time.Int64()/1000;
+ time = TTimeIntervalMicroSeconds(iVideoClip->EndTime());
+ iVideoClipParameters[i].iEndTime = time.Int64()/1000;
+ }
+
+ }
+
+ return;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::DeleteClipStructures
+// Frees memory allocated for internal structures
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::DeleteClipStructures()
+{
+
+ if (iFrameParameters)
+ User::Free(iFrameParameters);
+ iFrameParameters = 0;
+ iFrameParametersSize = 0;
+
+ if (iVideoClipParameters)
+ User::Free(iVideoClipParameters);
+ iVideoClipParameters = 0;
+
+ if (iEncoderBuffer)
+ User::Free(iEncoderBuffer);
+ iEncoderBuffer = 0;
+
+ if (iOutAudioBuffer)
+ delete iOutAudioBuffer;
+ iOutAudioBuffer=0;
+
+ if (iOutVideoBuffer)
+ delete iOutVideoBuffer;
+ iOutVideoBuffer = 0;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::InitializeClipL
+// Initializes the processor for processing a clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::InitializeClipL()
+{
+
+ PRINT((_L("CMovieProcessorImpl::InitializeClipL() begin")));
+
+ iFirstFrameOfClip = ETrue;
+ iFirstFrameFlagSet = EFalse;
+ iModeChanged = EFalse; /* assuming that this clip's mode has not been changed */
+ iVideoClipWritten = 0;
+ iWriting1stColorTransitionFrame = EFalse;
+
+ // update clip properties
+ if (iThumbnailInProgress)
+ {
+ // just get the first frame in normal mode
+ iSpeed = KMaxVideoSpeed;
+ iColorEffect = (TVedColorEffect)EVedColorEffectNone;
+ iStartCutTime = 0;
+ iEndCutTime = 10;
+ }
+ else
+ {
+ if (iNumberOfVideoClips)
+ {
+ if ( iVideoClip->Info()->FileHandle() )
+ {
+ iClipFileName.Zero();
+ iClipFileHandle = iVideoClip->Info()->FileHandle();
+ }
+ else
+ {
+ iClipFileHandle = NULL;
+ iClipFileName = (TPtrC)iVideoClip->Info()->FileName();
+ }
+
+ iSpeed = (TInt)iVideoClip->Speed();
+ iColorEffect = (TVedColorEffect)iVideoClip->ColorEffect();
+ iStartCutTime = TTimeIntervalMicroSeconds(iVideoClip->CutInTime());
+ iEndCutTime = TTimeIntervalMicroSeconds(iVideoClip->CutOutTime());
+
+ iColorToneRgb = iVideoClip->ColorTone();
+ ConvertColorToneRGBToYUV(iColorEffect,iColorToneRgb);
+ // store previous middle transition, if there is more than one middle transition
+ if(iVideoClipNumber > 0)
+ iPreviousMiddleTransitionEffect = iMiddleTransitionEffect;
+ // check if there is a position for middle transition for this clip
+ if(iMovie->MiddleTransitionEffectCount() > iVideoClipNumber)
+ {
+ iMiddleTransitionEffect = iMovie->MiddleTransitionEffect(iVideoClipNumber);
+
+ if( ( iMiddleTransitionEffect == EVedMiddleTransitionEffectCrossfade ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeLeftToRight ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeRightToLeft ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeTopToBottom ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeBottomToTop ) &&
+ ( iVideoClipNumber != iNumberOfVideoClips - 1 ) )
+ {
+ TParse filename, filepath;
+ CVedMovieImp* movie = (iMovie);
+
+ if( movie->VideoClip( iVideoClipNumber + 1 )->Info()->Class() == EVedVideoClipClassGenerated)
+ {
+ /************************************************************************/
+ TFileName ImageMovieName(KTempFilePath);
+ ImageMovieName.Append( _L( "Im_" ) );
+ ImageMovieName.Append( _L( "nokia_vpi.tmp" ) );
+ /************************************************************************/
+
+ filename.Set( ImageMovieName, NULL, NULL );
+
+ if (iOutputFileHandle)
+ {
+ RFile* file = iOutputFileHandle;
+ TFileName fullName;
+ TInt error = file->FullName(fullName);
+ filepath.Set(fullName, NULL, NULL);
+ }
+ else
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ }
+ else{
+
+ if ( movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileHandle() != NULL )
+ {
+
+ RFile* file = movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileHandle();
+
+ TFileName origName;
+ TInt error = file->Name(origName);
+ filename.Set(origName, NULL, NULL);
+
+ TFileName fullName;
+ error = file->FullName(fullName);
+ filepath.Set(fullName, NULL, NULL);
+
+ }
+ else
+ {
+ filename.Set( movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileName(), NULL, NULL );
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ }
+
+ }
+
+ iNextClipFileName = filepath.DriveAndPath();
+ iNextClipFileName.Append( filename.Name() );
+ // VPI special tmp file
+ iNextClipFileName.Append( _L( "_" ) );
+ iNextClipFileName.AppendNum( iVideoClipNumber );
+ iNextClipFileName.Append( _L( "_vpi.tmp" ) );
+ // try to create a tmp file
+ if ( iNextClip.Create( iFs, iNextClipFileName, EFileStream | EFileWrite | EFileShareExclusive ) != KErrNone )
+ {
+ // check if the tmp file exists
+ if ( iNextClip.Open( iFs, iNextClipFileName, EFileStream | EFileWrite | EFileShareExclusive ) != KErrNone )
+ {
+ iNextClip.Close();
+ iNextClipFileName.Zero();
+ }
+ }
+ }
+ }
+ }
+
+ // this is in common timescale
+ iInitialClipStartTimeStamp = (iVideoClipNumber>0 ? iVideoClipParameters[iVideoClipNumber-1].iEndTime : 0);
+ }
+
+ if (!iThumbnailInProgress)
+ iMonitor->StartPreparing();
+
+ // create an instance of the parser
+ if (iNumberOfVideoClips)
+ {
+
+ if (!iParser)
+ {
+ if (iClipFileHandle)
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileHandle);
+ else
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileName);
+ }
+ iParser->iFirstTimeClipParsing = ETrue;
+ iState = EStateIdle;
+ // open file & parse header
+ CMovieProcessorImpl::TDataFormat format = CMovieProcessorImpl::EDataAutoDetect;
+ User::LeaveIfError(OpenStream(iClipFileName, iClipFileHandle, format));
+
+ if ( iThumbnailInProgress && (iHaveVideo == EFalse) )
+ User::Leave(KErrNotFound);
+
+ VPASSERT(iState == EStateOpened);
+ }
+ else
+ SetHeaderDefaults();
+
+ iState = EStatePreparing;
+
+ if (!iThumbnailInProgress)
+ {
+
+ // Since the clip does not have any audio type it can be over written by any audio type depending on output
+ if(iOutputAudioType == EAudioAMR)
+ {
+ if( iAudioType == EAudioNone)
+ iAudioType = EAudioAMR;
+ }
+ else if(iOutputAudioType == EAudioAAC)
+ {
+ if( iAudioType == EAudioNone)
+ {
+ iAudioType = EAudioAAC;
+ if(iVideoClipNumber == 0)
+ {
+ //because it has no audio so it will have no decoder specific Info
+ iFirstClipHasNoDecInfo = ETrue;
+ }
+ iAudioFramesInSample = 1;
+ }
+ }
+
+ iEncoderInitPending = ETrue;
+ // complete request to finish initialising & start processing
+ SetActive();
+ iStatus = KRequestPending;
+
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+
+ if (iNumberOfVideoClips)
+ {
+ if (iParser)
+ {
+ // update the video clip duration in millisec.
+ iVideoClipDuration = (TInt64)(iVideoClip->Info()->Duration().Int64() *
+ (TInt64)iParser->iStreamParameters.iVideoTimeScale / (TInt64)(1000000));
+ }
+ }
+ }
+
+ else
+ {
+ // open demux & decoder
+ User::LeaveIfError(Prepare());
+
+ VPASSERT(iState == EStateReadyToProcess);
+ }
+
+ PRINT((_L("CMovieProcessorImpl::InitializeClipL() end")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::InitializeGeneratedClipL
+// Initializes the processor for processing a generated clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::InitializeGeneratedClipL()
+{
+ iEncodeInProgress = 0;
+ iFirstFrameOfClip = ETrue; // initialized to indicate that the first frame of this clip has not yet been written
+ iFirstFrameFlagSet = EFalse;
+ iModeChanged = EFalse; /* assuming that this clip's mode has not been changed */
+ iVideoClipWritten = 0;
+ iWriting1stColorTransitionFrame = EFalse;
+
+ // update clip properties
+ if (iThumbnailInProgress)
+ {
+ /* just get the first frame in normal mode */
+ iSpeed = KMaxVideoSpeed;
+ iColorEffect = (TVedColorEffect)EVedColorEffectNone;
+ iStartCutTime = 0;
+ iEndCutTime = 10;
+ }
+ else
+ {
+ if (iNumberOfVideoClips)
+ {
+ iSpeed = (TInt)iVideoClip->Speed();
+ iColorEffect = iVideoClip->ColorEffect();
+ iStartCutTime = TTimeIntervalMicroSeconds(0); /* since generated clips cannot be cut */
+ iEndCutTime = TTimeIntervalMicroSeconds(iVideoClip->Info()->Duration());
+
+ iColorToneRgb = iVideoClip->ColorTone();
+ ConvertColorToneRGBToYUV(iColorEffect,iColorToneRgb);
+
+ /* store previous middle transition, if there is more than one middle transition */
+ if(iVideoClipNumber > 0)
+ iPreviousMiddleTransitionEffect = iMiddleTransitionEffect;
+ /* since it is image clip, there will be no middletransitioneffect
+ check if there is a position for middle transition for this clip
+ */
+ if(iMovie->MiddleTransitionEffectCount() > iVideoClipNumber)
+ {
+ iMiddleTransitionEffect = iMovie->MiddleTransitionEffect(iVideoClipNumber);
+
+ if( ( iMiddleTransitionEffect == EVedMiddleTransitionEffectCrossfade ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeLeftToRight ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeRightToLeft ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeTopToBottom ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeBottomToTop ) &&
+ ( iVideoClipNumber != iNumberOfVideoClips - 1 ) )
+ {
+ TParse filename, filepath;
+ CVedMovieImp* movie = (iMovie);
+ if( movie->VideoClip( iVideoClipNumber + 1 )->Info()->Class() == EVedVideoClipClassGenerated)
+ {
+ /* path for storing temporary files */
+ TFileName ImageMovieName(KTempFilePath);
+ ImageMovieName.Append( _L( "Im_" ) );
+ ImageMovieName.Append( _L( "nokia_vpi.tmp" ) );
+ filename.Set( ImageMovieName, NULL, NULL );
+
+ if (iOutputFileHandle)
+ {
+ RFile* file = iOutputFileHandle;
+ TFileName fullName;
+ TInt error = file->FullName(fullName);
+ filepath.Set(fullName, NULL, NULL);
+ }
+ else
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ }
+ else
+ {
+ if ( movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileHandle() != NULL )
+ {
+ RFile* file = movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileHandle();
+
+ TFileName origName;
+ TInt error = file->Name(origName);
+ filename.Set(origName, NULL, NULL);
+
+ TFileName fullName;
+ error = file->FullName(fullName);
+ filepath.Set(fullName, NULL, NULL);
+ }
+ else
+ {
+ filename.Set( movie->VideoClip( iVideoClipNumber + 1 )->Info()->FileName(), NULL, NULL );
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ }
+ }
+
+ iNextClipFileName = filepath.DriveAndPath();
+ iNextClipFileName.Append( filename.Name() );
+ /* tag it to indicate that its a tmp editor file */
+ iNextClipFileName.Append( _L( "_" ) );
+ iNextClipFileName.AppendNum( iVideoClipNumber );
+ iNextClipFileName.Append( _L( "_vpi.tmp" ) );
+ /* try to create a tmp file */
+ if ( iNextClip.Create( iFs, iNextClipFileName, EFileStream | EFileWrite | EFileShareExclusive ) != KErrNone )
+ {
+ /* check if the tmp file exists */
+ if ( iNextClip.Open( iFs, iNextClipFileName, EFileStream | EFileWrite | EFileShareExclusive ) != KErrNone )
+ {
+ iNextClip.Close();
+ iNextClipFileName.Zero();
+ }
+ }
+ }
+ }
+ }
+
+ /* this is in common timescale */
+ iInitialClipStartTimeStamp = (iVideoClipNumber>0 ? iVideoClipParameters[iVideoClipNumber-1].iEndTime : 0);
+ }
+
+ if (iNumberOfVideoClips)
+ {
+
+ if (!iParser) /* if file name does not exist, this may cause error while parsing */
+ {
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileName);
+ }
+ else
+ {
+ delete iParser;
+ iParser = 0;
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileName);
+ }
+
+ iParser->iFirstTimeClipParsing = ETrue;
+ iState = EStateIdle;
+ /* open file and parse header */
+ CMovieProcessorImpl::TDataFormat format = CMovieProcessorImpl::EDataAutoDetect;
+ /* this will be overloaded to accomodate for the buffer type */
+
+ // HUOM! Meneekö tää oikein ??
+ User::LeaveIfError(OpenStream(iClipFileName, NULL, format));
+ VPASSERT(iState == EStateOpened);
+
+ }
+ else
+ {
+ SetHeaderDefaults();
+ }
+
+ iState = EStatePreparing;
+ if (!iThumbnailInProgress)
+ {
+
+ iEncoderInitPending = ETrue;
+ // async.
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+
+ if (iNumberOfVideoClips)
+ {
+ /* update the video clip duration in millisec. */
+ iVideoClipDuration = (TInt64)(iVideoClip->Info()->Duration().Int64() *
+ (TInt64)iParser->iStreamParameters.iVideoTimeScale / (TInt64)(1000000));
+ }
+
+ if(iOutputAudioType == EAudioAMR)
+ { // setting generated clip type same as output type
+ if( iAudioType == EAudioNone)
+ iAudioType = EAudioAMR;
+ }else if(iOutputAudioType == EAudioAAC)
+ {
+ if( iAudioType == EAudioNone)
+ iAudioType = EAudioAAC;
+ }
+
+ }
+ else /* if thumbnail is in progress */
+ {
+ /* open demux and decoder */
+ User::LeaveIfError(Prepare());
+ VPASSERT(iState == EStateReadyToProcess);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::TemporaryInitializeGeneratedClipL
+// temporarily initializes the processor for image 3gp file creation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::TemporaryInitializeGeneratedClipL(){
+
+ /* re-initialize to create new clip */
+ iFirstFrameOfClip = ETrue; /* initialized to indicate that the first frame of this clip has not yet been written */
+ iFirstFrameFlagSet = EFalse;
+ iModeChanged = EFalse; /* assuming that this clip's mode has not been changed */
+ iImageClipCreated = 0;
+ iWriting1stColorTransitionFrame = EFalse;
+
+ iImageEncodedFlag = 0; // has an image been encoded
+ iImageEncodeProcFinished = 0;
+ iFirstTimeProcessing = 0;
+ iGetFrameInProgress = 0;
+ iEncodeInProgress = 0;
+
+ TInt foundFileBased = 0;
+ TInt index = 0;
+ CVedVideoClip* tempclip =0;
+ CVedMovieImp* tempmovie = (iMovie);
+ TSize mRes = tempmovie->Resolution();
+
+ if(iVideoClipNumber == 0)
+ {
+ while(foundFileBased == 0)
+ {
+ if(index >= iNumberOfVideoClips)
+ {
+ break;
+ }
+ else
+ {
+ tempclip = tempmovie->VideoClip(index);
+ index++;
+ if(tempclip->Info()->Class()==EVedVideoClipClassGenerated)
+ {
+ foundFileBased = 0; //You still need to search
+ }
+ else
+ {
+ foundFileBased = 1;
+
+ if (tempclip->Info()->FileHandle())
+ {
+ iClipFileName.Zero();
+ iClipFileHandle = tempclip->Info()->FileHandle();
+ }
+ else
+ {
+ iClipFileHandle = NULL;
+ iClipFileName = tempclip->Info()->FileName();
+ }
+ }
+ }
+ }
+ tempmovie = 0; /* make them zero again */
+ tempclip = 0;
+ if(foundFileBased == 0) /* no file based clips in output movie */
+ {
+ iAllGeneratedClips =1; /* to indicate all clips to be inserted are generated */
+ iVideoParameters.iWidth = mRes.iWidth;
+ iVideoParameters.iHeight = mRes.iHeight;
+ }
+ else
+ {
+ /* create an instance of the parser which will be used to set stream paramters from file based */
+ if (iNumberOfVideoClips)
+ {
+ if (!iParser)
+ {
+ if (iClipFileHandle)
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileHandle);
+ else
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, iClipFileName);
+ }
+ iParser->iFirstTimeClipParsing = ETrue;
+ iState = EStateIdle;
+ /* open file and parse header */
+ iDataFormat = EData3GP; /* since file will be generated cant open with open stream so reset with standard */
+ iMuxType = EMux3GP;
+ ParseHeaderL();
+ }
+ }
+ }
+
+ iState = EStatePreparing;
+
+ if(iAllGeneratedClips == 1) /* all are generated clips => use H263 */
+ {
+ //iTranscoder->SetTargetVideoType(1); /* set target video type to H263 */
+ //not required as if all are generated even then output is based on engine output video type
+ }
+ iMonitor->StartPreparing();
+ if (!iVideoEncoder)
+ {
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ if (iOutputVideoType == EVideoAVCProfileBaseline)
+ {
+ VPASSERT(!iImageAvcEdit);
+ iImageAvcEdit = CVedAVCEdit::NewL();
+
+ iImageAvcEdit->SetOutputLevel( GetOutputAVCLevel() );
+ }
+
+#endif
+ iVideoEncoder = CVideoEncoder::NewL(iMonitor, iImageAvcEdit, iMovie->VideoCodecMimeType());
+
+ iVideoEncoder->SetFrameSizeL(iMovie->Resolution());
+
+ // Use the max frame rate since we don't want to change the frame rate
+ TReal inputFrameRate = iMovie->MaximumFramerate();
+ iVideoEncoder->SetInputFrameRate(inputFrameRate);
+
+ if ( iMovie->VideoFrameRate() > 0 )
+ iVideoEncoder->SetFrameRate( iMovie->VideoFrameRate() );
+ if ( iMovie->VideoBitrate() > 0 ) // if there is request for restricted bitrate, use it
+ iVideoEncoder->SetBitrate( iMovie->VideoBitrate() );
+ else if ( iMovie->VideoStandardBitrate() > 0 ) // use the given standard bitrate
+ iVideoEncoder->SetBitrate( iMovie->VideoStandardBitrate() );
+
+ if( iMovie->RandomAccessRate() > 0.0 )
+ iVideoEncoder->SetRandomAccessRate( iMovie->RandomAccessRate() );
+
+ /* initialize encoder */
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ iVideoEncoder->InitializeL(iStatus);
+ iEncoderInitPending = ETrue;
+ }
+ else
+ {
+ if((iAllGeneratedClips == 1) && (iVideoClipNumber == 0))
+ {
+ VPASSERT(iVideoEncoder->BeenStarted() == 0);
+ //iVideoEncoder->Stop();
+ delete iVideoEncoder;
+ iVideoEncoder = 0;
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ if (iOutputVideoType == EVideoAVCProfileBaseline)
+ {
+ VPASSERT(!iImageAvcEdit);
+ iImageAvcEdit = CVedAVCEdit::NewL();
+
+ iImageAvcEdit->SetOutputLevel( GetOutputAVCLevel() );
+ }
+#endif
+
+ iVideoEncoder = CVideoEncoder::NewL(iMonitor, iImageAvcEdit, iMovie->VideoCodecMimeType());
+
+ iVideoEncoder->SetFrameSizeL(iMovie->Resolution());
+
+ TReal inputFrameRate = iMovie->MaximumFramerate();
+ iVideoEncoder->SetInputFrameRate(inputFrameRate);
+
+ if ( iMovie->VideoFrameRate() > 0 )
+ iVideoEncoder->SetFrameRate( iMovie->VideoFrameRate() );
+ if ( iMovie->VideoBitrate() > 0 ) // if there is request for restricted bitrate, use it
+ iVideoEncoder->SetBitrate( iMovie->VideoBitrate() );
+ else if ( iMovie->VideoStandardBitrate() > 0 ) // use the given standard bitrate
+ iVideoEncoder->SetBitrate( iMovie->VideoStandardBitrate() );
+ if( iMovie->RandomAccessRate() > 0.0 )
+ iVideoEncoder->SetRandomAccessRate( iMovie->RandomAccessRate() );
+
+ /* initialize encoder */
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ iVideoEncoder->InitializeL(iStatus);
+ iEncoderInitPending = ETrue;
+ }
+ else
+ {
+ // first frame has to be intra
+ iVideoEncoder->SetRandomAccessPoint();
+ iEncoderInitPending = ETrue;
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+ }
+
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ParseHeaderOnlyL
+// Parses the header for a given clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ParseHeaderOnlyL(CParser::TStreamParameters& aStreamParams,
+ TFileName& aFileName, RFile* aFileHandle)
+{
+
+ if (!iParser)
+ {
+ // create an instance of the parser
+ if (aFileHandle)
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, aFileHandle);
+ else
+ iParser = (CMP4Parser*) CMP4Parser::NewL(this, aFileName);
+ }
+ iParser->ParseHeaderL(aStreamParams);
+
+ // don't read the audio properties from input files, but from audio engine
+ CVedMovieImp* songmovie = (iMovie);
+ CAudSong* songPointer = 0;
+
+ if (songmovie)
+ {
+ songPointer = songmovie->Song();
+ }
+
+ if (songPointer)
+ {
+ TAudFileProperties prop = songPointer->OutputFileProperties();
+
+ aStreamParams.iHaveAudio = ETrue;
+ if (songPointer->ClipCount(KAllTrackIndices) == 0)
+ {
+ aStreamParams.iHaveAudio = EFalse;
+ }
+
+ aStreamParams.iAudioLength = I64INT(prop.iDuration.Int64())/1000;
+ aStreamParams.iAudioFormat = CParser::EAudioFormatNone;
+ if (prop.iAudioType == EAudAMR)
+ {
+ aStreamParams.iAudioFormat = CParser::EAudioFormatAMR;
+ aStreamParams.iAudioFramesInSample = 5;
+ aStreamParams.iAudioTimeScale = 1000;
+ }
+ else if ( prop.iAudioType == EAudAAC_MPEG4 )
+ {
+ aStreamParams.iAudioFormat = CParser::EAudioFormatAAC;
+ aStreamParams.iAudioFramesInSample = 1;
+ aStreamParams.iAudioTimeScale = prop.iSamplingRate;
+ }
+ }
+
+ // update output parameters.
+ UpdateStreamParameters(iParser->iStreamParameters, aStreamParams);
+ SetOutputNumberOfFrames(iParser->iOutputNumberOfFrames);
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::OpenStream
+// Opens a clip for processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::OpenStream(TFileName aFileName, RFile* aFileHandle, TDataFormat aDataFormat)
+{
+ // We can only streams in idle state
+ if (iState != EStateIdle)
+ return EInvalidProcessorState;
+
+ TInt error = KErrNone;
+ iDataFormat = aDataFormat;
+
+ if (!aFileHandle)
+ {
+
+ RFs fs;
+ RFile file;
+
+ if(aFileName.Length() == 0)
+ return KErrArgument;
+
+ // Open a file server session and open the file:
+ if ( (error = fs.Connect()) != KErrNone )
+ return error;
+
+ if ( (error = file.Open(fs, aFileName, EFileShareReadersOnly | EFileRead)) != KErrNone )
+ {
+ if ( (error = file.Open(fs, aFileName, EFileShareAny | EFileRead)) != KErrNone )
+ {
+ return error;
+ }
+ }
+
+ // set descriptor to read buffer
+ TPtr8 readDes(0,0);
+ readDes.Set(iReadBuf, 0, KReadBufInitSize);
+
+ // read data from the file
+ if ( (error = file.Read(readDes)) != KErrNone )
+ return error;
+
+ if ( readDes.Length() < 8 )
+ return KErrGeneral;
+
+ file.Close();
+ fs.Close();
+
+ // detect if format is 3GP, 5-8 == "ftyp"
+ // This method is not 100 % proof, but good enough
+ if ( (iReadBuf[4] == 0x66) && (iReadBuf[5] == 0x74) &&
+ (iReadBuf[6] == 0x79) && (iReadBuf[7] == 0x70) )
+ {
+ iDataFormat = EData3GP;
+ iMuxType = EMux3GP;
+ }
+ else
+ return KErrNotSupported;
+ }
+
+ // FIXME
+ iDataFormat = EData3GP;
+ iMuxType = EMux3GP;
+
+ // parse 3GP header
+ CMP4Parser *parser = 0;
+ if ( !iParser )
+ {
+ if (iClipFileHandle)
+ {
+ TRAP(error, (parser = CMP4Parser::NewL(this, iClipFileHandle)) );
+ }
+ else
+ {
+ TRAP(error, (parser = CMP4Parser::NewL(this, iClipFileName)) );
+ }
+
+ if (error != KErrNone)
+ return error;
+ iParser = parser;
+ }
+ else
+ parser = (CMP4Parser*)iParser;
+
+ TRAP(error, ParseHeaderL());
+
+ if (error != KErrNone)
+ return error;
+
+ iState = EStateOpened;
+
+ return KErrNone;
+
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CloseStream
+// Closes the processed stream from parser
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::CloseStream()
+{
+
+ PRINT((_L("CMovieProcessorImpl::CloseStream() begin - iState = %d"), iState))
+
+ if ( (iState != EStateOpened) && (iState != EStateProcessing) )
+ return EInvalidProcessorState;
+
+ TInt error=0;
+
+ // delete parser
+ if (iParser)
+ {
+ TRAP(error,
+ {
+ delete iParser;
+ iParser=0;
+ }
+ );
+ if (error != KErrNone)
+ return error;
+ }
+
+ iClipFileName.Zero();
+ iCurrentMovieName.Zero();
+
+ // We are idle again
+ iState = EStateIdle;
+
+ PRINT((_L("CMovieProcessorImpl::CloseStream() end ")))
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::Prepare
+// Prepares the processor for processing, opens demux & decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::Prepare()
+{
+ TInt error;
+ TUint videoBlockSize, videoBlocks;
+
+ // We can only prepare from preparing state
+ if (iState != EStatePreparing)
+ return EInvalidProcessorState;
+
+ // Make sure we now know the stream format
+ if (iDataFormat == EDataAutoDetect)
+ return EUnsupportedFormat;
+
+ // Check whether the stream has audio, video or both, and whether it is
+ // muxed
+ switch (iDataFormat)
+ {
+ case EData3GP:
+ // the video and audio flags are set when
+ // the header is parsed.
+ iIsMuxed = ETrue;
+ break;
+ default:
+ User::Panic(_L("CMovieProcessorImpl"), EInvalidInternalState);
+ }
+
+ // If we have already played this stream since opening it, we'll have to
+ // try to rewind
+
+ // only 3gp file format supported => iIsMuxed always true
+ videoBlocks = KVideoQueueBlocks;
+ videoBlockSize = KVideoQueueBlockSize;
+
+ // Initialize video
+ VPASSERT((!iVideoQueue) && (!iVideoProcessor));
+ if (iHaveVideo)
+ {
+ TRAP(error, InitVideoL(videoBlocks, videoBlockSize));
+ if ( error != KErrNone )
+ return error;
+ }
+
+ // Initialize demux
+ VPASSERT(!iDemux);
+ VPASSERT(iIsMuxed);
+ TRAP(error, InitDemuxL());
+ if ( error != KErrNone )
+ return error;
+
+ iState = EStateReadyToProcess;
+
+ return KErrNone;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::InitVideoL
+// Initializes the video decoder for processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::InitVideoL(TUint aQueueBlocks, TUint aQueueBlockSize)
+{
+ // Create video input queue
+ iVideoQueue = new (ELeave) CActiveQueue(aQueueBlocks, aQueueBlockSize);
+ iVideoQueue->ConstructL();
+
+ if (iThumbnailInProgress &&
+ iParser->iStreamParameters.iVideoFormat == CParser::EVideoFormatAVCProfileBaseline)
+ {
+ if (!iAvcEdit)
+ {
+ // create AVC editing instance
+ iAvcEdit = CVedAVCEdit::NewL();
+ }
+ }
+
+ // Create correct video decoder object
+
+ VPASSERT(!iVideoProcessor);
+ switch (iVideoType)
+ {
+ case EVideoH263Profile0Level10:
+ case EVideoH263Profile0Level45:
+ case EVideoMPEG4:
+ case EVideoAVCProfileBaseline:
+ // H.263 decoder handles both H.263+ and MPEG-4
+ {
+
+ iVideoProcessor = CVideoProcessor::NewL(iVideoQueue,
+ &iVideoParameters,
+ this,
+ iMonitor,
+ iAvcEdit,
+ iThumbnailInProgress,
+ CActive::EPriorityStandard);
+
+ }
+ break;
+
+ default:
+ User::Leave(EUnsupportedFormat);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::InitDemuxL
+// Initializes the demultiplexer for processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::InitDemuxL()
+{
+
+ // Set video channel target queue
+ TUint i;
+
+ // 3gp is the only supported file format
+ VPASSERT(iMuxType == EMux3GP);
+
+ for ( i = 0; i < iNumDemuxChannels; i++ )
+ {
+ if (iMP4Channels[i].iDataType == CMP4Demux::EDataVideo)
+ {
+ VPASSERT(iHaveVideo);
+ iMP4Channels[i].iTargetQueue = iVideoQueue;
+ }
+ }
+
+ VPASSERT(iParser);
+
+ iDemux = CMP4Demux::NewL(NULL /* demuxQueue */, iNumDemuxChannels,
+ iMP4Channels, &iMP4Parameters,
+ iMonitor, (CMP4Parser*)iParser,
+ KDemuxPriority);
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::DoStartProcessing
+// Starts processing the movie
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::DoStartProcessing()
+{
+
+ PRINT((_L("CMovieProcessorImpl::DoStartProcessing() begin")))
+
+ if (iNumberOfVideoClips)
+ {
+ VPASSERT(iDemux);
+ VPASSERT(iVideoProcessor);
+ VPASSERT(iState == EStateReadyToProcess);
+
+ // start demuxing & decoding video
+
+ iDemux->Start();
+ iVideoProcessor->Start();
+ if(!((iVideoClipNumber==0)&&((TVedVideoClipClass)iVideoClip->Info()->Class()==(TVedVideoClipClass)EVedVideoClipClassGenerated)))
+ iMonitor->ProcessingStarted(iStartingProcessing);
+ iStartingProcessing = EFalse;
+ iState = EStateProcessing;
+ }
+ else
+ {// audio-only case
+
+ iState = EStateProcessing;
+ iMonitor->ProcessingStarted(EFalse);
+
+ TRAPD( error, iObserver->NotifyMovieProcessingStartedL(*iMovie) );
+ if (error != KErrNone)
+ {
+ if (iMonitor)
+ iMonitor->Error(error);
+ return;
+ }
+
+ // process all audio clips
+ ProcessAudioOnly();
+ }
+
+ PRINT((_L("CMovieProcessorImpl::DoStartProcessing() end")))
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ProcessAudioOnly
+// Processes the movie in audio-only case
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ProcessAudioOnly()
+{
+
+ VPASSERT(iNumberOfAudioClips > 0);
+
+ // write audio frames to file & encode a black video frame
+ TInt error;
+ TRAP(error, ProcessAudioL());
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+
+ //VPASSERT(iEncodePending);
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::DoCloseVideoL
+// Closes & deletes the structures used in processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::DoCloseVideoL()
+{
+ if ((iState == EStateProcessing) || (iState == EStateReadyToProcess)||
+ (iState == EStatePreparing) )
+ {
+ PRINT((_L("CMovieProcessorImpl::DoCloseVideoL() - stopping")))
+ User::LeaveIfError(Stop());
+ iState = EStateOpened;
+ }
+
+ // If we are buffering or opening at the moment or clip is open then close it
+ if ( (iState == EStateOpened) || (iState == EStateReadyToProcess))
+ {
+ PRINT((_L("CMovieProcessorImpl::DoCloseVideoL() - closing stream")))
+ User::LeaveIfError(CloseStream());
+ iState = EStateIdle;
+ }
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::Stop
+// Stops processing & closes modules used in processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::Stop()
+{
+ TInt error = KErrNone;
+
+ // Check state
+ if ( (iState != EStateProcessing) && (iState != EStateReadyToProcess) && (iState != EStatePreparing) )
+ return EInvalidProcessorState;
+ // We may also get here from the middle of a Prepare() attempt.
+
+ PRINT((_L("CMovieProcessorImpl::Stop() begin")))
+
+ // Destroy the playback objects to stop playback
+ TRAP(error,
+ {
+ if (iDemux)
+ delete iDemux;
+ iDemux = 0;
+
+ if (iAudioProcessor)
+ delete iAudioProcessor;
+ iAudioProcessor = 0;
+
+ });
+ if (error != KErrNone)
+ return error;
+
+
+ if (iVideoEncoder)
+ {
+ if (!iEncoderInitPending)
+ {
+ // Delete encoder. Don't delete now if encoding
+ // is not in progress at encoder and there are
+ // active encoding flags. This means that encoder
+ // has completed encoding request, but this->RunL()
+ // hasn't been called yet. Encoder will be deleted in RunL()
+
+ if ( ( iVideoEncoder->IsEncodePending() == 1 ) ||
+ ( (!iEncodePending && !iEncodeInProgress) ) )
+ {
+ PRINT((_L("CMovieProcessorImpl::Stop() - deleting encoder")));
+ Cancel();
+ iVideoEncoder->Stop();
+ delete iVideoEncoder;
+ iVideoEncoder = 0;
+ }
+ }
+ }
+
+ if (iVideoProcessor)
+ delete iVideoProcessor;
+ iVideoProcessor = 0;
+
+ if (iVideoQueue)
+ delete iVideoQueue;
+ iVideoQueue = 0;
+
+ if (!iThumbnailInProgress && iState == EStateProcessing)
+ {
+ if (iMonitor)
+ iMonitor->ProcessingStopped();
+ }
+
+ iState = EStateOpened;
+
+ PRINT((_L("CMovieProcessorImpl::Stop() end")))
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::Close
+// Stops processing and closes all submodules except status monitor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::Close()
+{
+
+ // delete all objects except status monitor
+ delete iComposer;
+ iComposer = 0;
+ DeleteClipStructures();
+ TRAPD(error, DoCloseVideoL());
+ if (error != KErrNone)
+ return error;
+
+ iState = EStateIdle;
+
+ return KErrNone;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::RunL
+// Called by the active scheduler when the video encoder initialization is done
+// or an ending black frame has been encoded
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::RunL()
+{
+
+ PRINT((_L("RunL begin, iEncoderInitPending %d, iEncodePending %d, iEncodeInProgress %d"),
+ iEncoderInitPending, iEncodePending, iEncodeInProgress ));
+
+ PRINT((_L("CMovieProcessorImpl::RunL begin - iEncodeInProgress %d"), iEncodeInProgress));
+
+ if (iAudioProcessingCompleted)
+ {
+ iAudioProcessingCompleted = EFalse;
+ FinalizeVideoSequenceL();
+ return;
+ }
+
+ if (iNumberOfVideoClips)
+ {
+ // If we come here after a generated 3gp clip has been created,
+ // ival == EVedVideoClipClassGenerated && iImageClipCreated == 1
+
+ TVedVideoClipClass ival = (TVedVideoClipClass)iVideoClip->Info()->Class();
+ if(ival == EVedVideoClipClassGenerated && iImageClipCreated == 0) // iImageClipCreated will work only for single imageset currently
+ {
+ iEncoderInitPending = EFalse; // is this correct ??
+ DoImageSetProcessL(); // Call function which does image file creation
+ return;
+ }
+ }
+
+ if (iEncoderInitPending)
+ {
+ VPASSERT(!iEncodePending);
+
+ PRINT((_L("CMovieProcessorImpl::RunL - encoder init complete")));
+ // video encoder has been initialized => start processing
+
+ iEncoderInitPending = EFalse;
+
+ if (iProcessingCancelled)
+ {
+ PRINT((_L("CMovieProcessorImpl::RunL - processing cancelled")));
+ if (iVideoEncoder)
+ {
+ iVideoEncoder->Stop();
+ delete iVideoEncoder;
+ iVideoEncoder = 0;
+ }
+ PRINT((_L("CMovieProcessorImpl::RunL - calling cancelled callback")));
+ if (iMonitor)
+ iMonitor->ProcessingCancelled();
+
+ return;
+ }
+
+ if (iEncodingBlackFrames)
+ {
+ FinalizeVideoSequenceL();
+ return;
+ }
+
+ if (iNumberOfVideoClips)
+ {
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ CVedVideoClipInfo* currentInfo = iVideoClip->Info();
+
+ // Save SPS/PPS data from input file even if output type
+ // is not AVC. This data is needed in doing blending transitions
+ // from AVC input to H.263/MPEG-4 output. An optimisation
+ // could be to check if such transitions are present in movie
+ // and save only when necessary.
+
+ if ( (currentInfo->Class() == EVedVideoClipClassFile &&
+ currentInfo->VideoType() == EVedVideoTypeAVCBaselineProfile) ||
+ (iOutputVideoType == EVideoAVCProfileBaseline &&
+ currentInfo->Class() == EVedVideoClipClassGenerated) )
+ {
+ // save SPS/PPS NAL units
+ TInt size = iParser->GetDecoderSpecificInfoSize();
+ HBufC8* buf = (HBufC8*) HBufC8::NewLC(size);
+ TPtr8 ptr = buf->Des();
+ User::LeaveIfError( iParser->ReadAVCDecoderSpecificInfo(ptr) );
+ iAvcEdit->SaveAVCDecoderConfigurationRecordL(ptr, EFalse);
+ CleanupStack::PopAndDestroy(); // buf
+ }
+#endif
+
+ // go to the beginning of the I frame immediately preceding the start cut time
+ User::LeaveIfError(iParser->SeekOptimalIntraFrame(iStartCutTime, 0, ETrue));
+
+ TInt currentFrameIndex = iOutputNumberOfFrames;
+
+ // update parameters
+ SetOutputNumberOfFrames(iParser->iOutputNumberOfFrames);
+
+ // fill in frame parameters
+ FillFrameParametersL(currentFrameIndex);
+
+ // open video decoder & demux
+ User::LeaveIfError(Prepare());
+ }
+ // if ( iVideoClipNumber > 0 || class != generated )
+ if( iNumberOfVideoClips == 0 || !( (iVideoClipNumber==0) && ((TVedVideoClipClass)iVideoClip->Info()->Class()==(TVedVideoClipClass)EVedVideoClipClassGenerated)) )
+ iMonitor->PrepareComplete();
+
+ // start processing
+ DoStartProcessing();
+ }
+
+ else if (iEncodePending)
+ {
+ // encoding complete
+ iEncodePending = EFalse;
+
+ TInt64 frameDuration; // in ticks
+ if ( iLeftOverDuration >= 1000 )
+ {
+ iLeftOverDuration -= 1000;
+ frameDuration = iOutputVideoTimeScale; // One second in ticks
+ }
+ else
+ {
+ iLeftOverDuration = 0;
+ frameDuration = TInt64( TReal(iOutputVideoTimeScale)/1000.0 * I64REAL(iLeftOverDuration) + 0.5 );
+ }
+
+ if (iStatus == KErrNone)
+ {
+ // Audio-only or audio longer than video
+ // => black frame is encoded at the end
+
+ PRINT((_L("CMovieProcessorImpl::RunL - encoding complete")));
+
+ // fetch the bitstream & write it to output file, release bitstream buffer
+ TBool isKeyFrame = 0;
+ TPtrC8 buf(iVideoEncoder->GetBufferL(isKeyFrame));
+
+ TReal tsInTicks = I64REAL(iTimeStamp.Int64() / TInt64(1000)) * TReal(iOutputVideoTimeScale) / 1000.0;
+
+ User::LeaveIfError( WriteVideoFrameToFile((TDesC8&)buf, TInt64(tsInTicks + 0.5), I64INT(frameDuration),
+ isKeyFrame, ETrue, EFalse, ETrue ) );
+
+ iVideoEncoder->ReturnBuffer();
+
+ // do not reset flag until here so that last frame of last clip gets the correct
+ // duration in case slow motion is used
+ iApplySlowMotion = EFalse;
+ }
+#ifdef _DEBUG
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::RunL - encoding failed")));
+ }
+#endif
+
+ iTimeStamp = TTimeIntervalMicroSeconds(iTimeStamp.Int64() + TInt64(1000000));
+
+ if (iLeftOverDuration > 0)
+ {
+ // encode another frame
+ VPASSERT(iEncoderBuffer);
+ TSize tmpSize = iMovie->Resolution();
+ TUint yLength = tmpSize.iWidth * tmpSize.iHeight;
+ TUint uvLength = yLength >> 1;
+ TUint yuvLength = yLength + uvLength;
+ TPtr8 yuvPtr(iEncoderBuffer, yuvLength, yuvLength);
+
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+
+ iVideoEncoder->EncodeFrameL(yuvPtr, iStatus, iTimeStamp);
+ iEncodePending = ETrue;
+
+ }
+ else
+ {
+ // movie complete, close everything
+
+ TInt error = FinalizeVideoWrite();
+ if (error != KErrNone)
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ error = iComposer->Close(); // creates the output file
+ if (error != KErrNone)
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ // delete all objects except status monitor
+ delete iComposer;
+ iComposer = 0;
+
+ if(iImageComposer)
+ {
+ delete iImageComposer;
+ iImageComposer=0;
+ }
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+
+ DeleteClipStructures();
+
+ DoCloseVideoL();
+
+ VPASSERT(!iEncoderInitPending);
+
+ PRINT((_L("CMovieProcessorImpl::RunL - calling completed callback")));
+ iMonitor->ProcessingComplete();
+ iState = EStateIdle;
+ }
+
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::RunError
+// Called by the AO framework when RunL method has leaved
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::RunError(TInt aError)
+{
+
+ if ( iCurClipFileName.Length() )
+ {
+ iCurClip.Close();
+ iFs.Delete( iCurClipFileName );
+ iCurClipFileName.Zero();
+ iCurClipDurationList.Reset();
+ iCurClipTimeStampList.Reset();
+ }
+
+ iMonitor->Error(aError);
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::DoCancel
+// Cancels any pending asynchronous requests
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::DoCancel()
+{
+
+ PRINT((_L("CMovieProcessorImpl::DoCancel() begin")))
+
+ // Cancel our internal request
+ if ( iStatus == KRequestPending )
+ {
+ PRINT((_L("CMovieProcessorImpl::DoCancel() cancel request")))
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrCancel);
+ }
+
+ PRINT((_L("CMovieProcessorImpl::DoCancel() end")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SetHeaderDefaults
+// Sets appropriate default values for processing parameters
+// in audio-only case
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::SetHeaderDefaults()
+{
+
+ // set suitable default values
+ iHaveVideo = ETrue;
+ iVideoType = EVideoH263Profile0Level10;
+ iHaveAudio = ETrue;
+ iAudioType = EAudioAMR;
+ iNumDemuxChannels = 0;
+
+ // resolution from movie
+ TSize tmpSize = iMovie->Resolution();
+ iVideoParameters.iWidth = tmpSize.iWidth;
+ iVideoParameters.iHeight = tmpSize.iHeight;
+ iVideoParameters.iIntraFrequency = 0;
+ iVideoParameters.iNumScalabilityLayers = 0;
+ iVideoParameters.iReferencePicturesNeeded = 0;
+ // picture period in nanoseconds
+ iVideoParameters.iPicturePeriodNsec = TInt64(33366667);
+
+ // output time scales
+ iOutputVideoTimeScale = KVideoTimeScale;
+ iOutputAudioTimeScale = KAMRAudioTimeScale;
+
+ iStreamLength = 0;
+ iStreamSize = 0;
+ iStreamBitrate = 10000;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ParseHeaderL
+// Parses the clip header & sets internal variables accordingly
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ParseHeaderL()
+{
+ TInt i;
+
+ VPASSERT(iParser);
+
+ if ( iMuxType != EMux3GP )
+ User::Leave(EUnsupportedFormat);
+
+ CParser::TStreamParameters streamParams;
+
+ // parse
+ iParser->ParseHeaderL(streamParams);
+
+ // don't read the audio properties from input files, but from audio engine
+ CVedMovieImp* songmovie = (iMovie);
+ CAudSong* songPointer = 0;
+
+ if (songmovie)
+ {
+ songPointer = songmovie->Song();
+ }
+
+ if (songPointer)
+ {
+
+ TAudFileProperties prop = songPointer->OutputFileProperties();
+
+ streamParams.iHaveAudio = ETrue;
+ if (songPointer->ClipCount(KAllTrackIndices) == 0)
+ {
+ streamParams.iHaveAudio = EFalse;
+ }
+
+ streamParams.iAudioLength = I64INT(prop.iDuration.Int64())/1000;
+ streamParams.iAudioFormat = CParser::EAudioFormatNone;
+ if (prop.iAudioType == EAudAMR)
+ {
+ streamParams.iAudioFormat = CParser::EAudioFormatAMR;
+ streamParams.iAudioFramesInSample = 5;
+ streamParams.iAudioTimeScale = 1000;
+ }
+ else if ( prop.iAudioType == EAudAAC_MPEG4 )
+ {
+ streamParams.iAudioFormat = CParser::EAudioFormatAAC;
+ streamParams.iAudioFramesInSample = 1;
+ streamParams.iAudioTimeScale = prop.iSamplingRate;
+ }
+ }
+
+ // copy input stream info into parser
+ UpdateStreamParameters(iParser->iStreamParameters, streamParams);
+
+ // copy parameters
+ iHaveVideo = streamParams.iHaveVideo;
+ iVideoType = (TVideoType)streamParams.iVideoFormat;
+ iHaveAudio = streamParams.iHaveAudio;
+ iAudioType = (TAudioType)streamParams.iAudioFormat;
+ iNumDemuxChannels = streamParams.iNumDemuxChannels;
+ iCanSeek = streamParams.iCanSeek;
+ iVideoParameters.iWidth = streamParams.iVideoWidth;
+ iVideoParameters.iHeight = streamParams.iVideoHeight;
+ iVideoParameters.iIntraFrequency = streamParams.iVideoIntraFrequency;
+ iVideoParameters.iNumScalabilityLayers = streamParams.iNumScalabilityLayers;
+ iVideoParameters.iReferencePicturesNeeded = streamParams.iReferencePicturesNeeded;
+ iVideoParameters.iPicturePeriodNsec = streamParams.iVideoPicturePeriodNsec;
+
+ for (i = 0; i < (TInt)streamParams.iNumScalabilityLayers; i++)
+ iVideoParameters.iLayerFrameRates[i] = streamParams.iLayerFrameRates[i];
+
+
+ // assign time scale values
+ if((iVideoClipNumber==0) && (iOutputVideoTimeSet==0))
+ {
+ iOutputVideoTimeSet = 1;
+ iOutputVideoTimeScale = KVideoTimeScale;
+ }
+
+ // change the start and end times of the video clip from msec to ticks
+ iVideoClipParameters[iVideoClipNumber].iStartTime = TInt64( TReal(iOutputVideoTimeScale)/1000.0 *
+ I64REAL(iVideoClipParameters[iVideoClipNumber].iStartTime) );
+
+ iVideoClipParameters[iVideoClipNumber].iEndTime = TInt64( TReal(iOutputVideoTimeScale)/1000.0 *
+ I64REAL(iVideoClipParameters[iVideoClipNumber].iEndTime) );
+
+ iVideoParameters.iTiming = CVideoProcessor::ETimeStamp;
+ iMP4Parameters.iPicturePeriodMs = I64INT( (iVideoParameters.iPicturePeriodNsec / TInt64(1000000)) );
+ iMP4Parameters.iAudioFramesInSample = streamParams.iAudioFramesInSample;
+
+
+ if ( iHaveVideo )
+ {
+ iMP4Channels[0].iDataType = CMP4Demux::EDataVideo;
+ }
+
+ if ( iHaveAudio ) {
+
+ iNumDemuxChannels = 1;
+
+ // NOTE: audio is processed 'off-line' after a video
+ // clip has been processed.
+
+ //iMP4Channels[i].iDataType = CMP4Demux::EDataAudio;
+ }
+
+ iStreamLength = streamParams.iStreamLength;
+ iStreamBitrate = streamParams.iStreamBitrate;
+ iStreamSize = streamParams.iStreamSize;
+
+ // Ensure that the video isn't too large
+ if (!iThumbnailInProgress)
+ {
+ if ( (iVideoParameters.iWidth > KVedMaxVideoWidth) ||
+ (iVideoParameters.iHeight > KVedMaxVideoHeight) )
+ User::Leave(EVideoTooLarge);
+ }
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::UpdateStreamParameters
+// Copies stream parameters to destination structure
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::UpdateStreamParameters(CParser::TStreamParameters& aDestParameters,
+ CParser::TStreamParameters& aSrcParameters)
+{
+ TInt i;
+ aDestParameters.iHaveVideo = aSrcParameters.iHaveVideo;
+ aDestParameters.iHaveAudio = aSrcParameters.iHaveAudio;
+ aDestParameters.iNumDemuxChannels = aSrcParameters.iNumDemuxChannels;
+ aDestParameters.iFileFormat = aSrcParameters.iFileFormat;
+ aDestParameters.iVideoFormat = aSrcParameters.iVideoFormat;
+ aDestParameters.iAudioFormat = aSrcParameters.iAudioFormat;
+ aDestParameters.iAudioFramesInSample = aSrcParameters.iAudioFramesInSample;
+ aDestParameters.iVideoWidth = aSrcParameters.iVideoWidth;
+ aDestParameters.iVideoHeight = aSrcParameters.iVideoHeight;
+ aDestParameters.iVideoPicturePeriodNsec = aSrcParameters.iVideoPicturePeriodNsec;
+ aDestParameters.iVideoIntraFrequency = aSrcParameters.iVideoIntraFrequency;
+ aDestParameters.iStreamLength = aSrcParameters.iStreamLength;
+ aDestParameters.iVideoLength = aSrcParameters.iVideoLength;
+ aDestParameters.iAudioLength = aSrcParameters.iAudioLength;
+ aDestParameters.iCanSeek = aSrcParameters.iCanSeek;
+ aDestParameters.iStreamSize = aSrcParameters.iStreamSize;
+ aDestParameters.iStreamBitrate = aSrcParameters.iStreamBitrate;
+ aDestParameters.iMaxPacketSize = aSrcParameters.iMaxPacketSize;
+ aDestParameters.iLogicalChannelNumberVideo = aSrcParameters.iLogicalChannelNumberVideo;
+ aDestParameters.iLogicalChannelNumberAudio = aSrcParameters.iLogicalChannelNumberAudio;
+ aDestParameters.iReferencePicturesNeeded = aSrcParameters.iReferencePicturesNeeded;
+ aDestParameters.iNumScalabilityLayers = aSrcParameters.iNumScalabilityLayers;
+ for(i=0; i<(TInt)aSrcParameters.iNumScalabilityLayers; i++)
+ aDestParameters.iLayerFrameRates[i] = aSrcParameters.iLayerFrameRates[i];
+
+ aDestParameters.iFrameRate = aSrcParameters.iFrameRate;
+ aDestParameters.iVideoTimeScale = aSrcParameters.iVideoTimeScale;
+ aDestParameters.iAudioTimeScale = aSrcParameters.iAudioTimeScale;
+
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FinalizeVideoClip
+// Finalizes video clip once all its frames are processed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::FinalizeVideoClip()
+{
+
+ PRINT((_L("CMovieProcessorImpl::FinalizeVideoClip() begin")))
+
+ TInt error = KErrNone;
+
+ TInt64 endPosition = TInt64(iCurrentVideoTimeInTicks + 0.5);
+
+ if ( TransitionDuration() )
+ {
+ endPosition += TInt64( (TReal)TransitionDuration() * (TReal)iOutputVideoTimeScale / (TReal)iParser->iStreamParameters.iVideoTimeScale + 0.5);
+ }
+
+ // convert time from ticks to millisec.
+ endPosition = GetVideoTimeInMsFromTicks( endPosition, ETrue );
+
+ CVedMovieImp* movie = (iMovie);
+
+ iLeftOverDuration = movie->Duration().Int64()/1000 -
+ movie->VideoClip(iNumberOfVideoClips-1)->EndTime().Int64()/1000;
+
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+
+ // if last video clip in movie
+ if(iVideoClipNumber == iNumberOfVideoClips-1 || iMovieSizeLimitExceeded)
+ {
+ iAllVideoProcessed = ETrue;
+ if ( iFsConnected )
+ {
+ TRAP(error, CloseTransitionInfoL());
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ iFs.Close();
+ iFsConnected = EFalse;
+ }
+
+ // process all audio
+ TRAP(error, ProcessAudioL());
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ }
+ else // process the next clip
+ {
+
+ if (iCurClipFileName.Length() )
+ {
+ iCurClip.Close();
+ error = iFs.Delete( iCurClipFileName );
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ iCurClipFileName.Zero();
+ iCurClipDurationList.Reset();
+ iCurClipTimeStampList.Reset();
+ iTimeStampListScaled = EFalse;
+ }
+
+ if ( iNextClipFileName.Length() )
+ {
+ iNextClip.Close();
+ }
+
+ // close the video
+ TRAP(error, DoCloseVideoL());
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+
+ if ( iNextClipFileName.Length() )
+ {
+ error = iFs.Delete( iNextClipFileName );
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ iNextClipFileName.Zero();
+ iNextClipDurationList.Reset();
+ iNextClipTimeStampList.Reset();
+ }
+ return;
+ }
+ iMonitor->Closed();
+
+ if ( iFsConnected )
+ {
+ CFileMan *fileMan = 0;
+ TRAP(error, fileMan = CFileMan::NewL( iFs ));
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ TParse filepath;
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ TFileName filesToDelete = filepath.DriveAndPath();
+ filesToDelete.Append( _L( "Im_nokia_vpi.tmp" ) );
+ fileMan->Delete( filesToDelete,0 );
+ delete fileMan;
+ }
+
+ // copy from current to next
+ iCurClipFileName = iNextClipFileName;
+ iNextClipFileName.Zero();
+ TInt duration;
+ TInt64 timestamp;
+ while ( iNextClipDurationList.Count() )
+ {
+ duration = iNextClipDurationList[0];
+ iNextClipDurationList.Remove( 0 );
+ iCurClipDurationList.Append( duration );
+ timestamp = iNextClipTimeStampList[0];
+ iNextClipTimeStampList.Remove( 0 );
+ iCurClipTimeStampList.Append( timestamp );
+ }
+
+ iNextClipDurationList.Reset();
+ iNextClipTimeStampList.Reset();
+ iCurClipIndex = 0;
+
+ if ( iCurClipFileName.Length() )
+ {
+ if ( iCurClip.Open(iFs, iCurClipFileName, EFileShareReadersOnly | EFileStream | EFileRead) != KErrNone )
+ {
+ if ( iCurClip.Open(iFs, iCurClipFileName, EFileShareAny | EFileStream | EFileRead) != KErrNone )
+ {
+ iCurClip.Close();
+ iCurClipFileName.Zero();
+ iCurClipDurationList.Reset();
+ iCurClipTimeStampList.Reset();
+ }
+ }
+ }
+
+ VPASSERT(!iEncoderInitPending);
+
+ // go to next clip
+ iVideoClipNumber++;
+ iVideoClip = movie->VideoClip(iVideoClipNumber);
+
+ if(iVideoClip->Info()->Class() == EVedVideoClipClassGenerated)
+ {
+ TRAP(error, TemporaryInitializeGeneratedClipL());
+ }
+ else
+ {
+ TRAP(error, InitializeClipL());
+ }
+ if (error != KErrNone)
+ {
+ if ( iCurClipFileName.Length() )
+ {
+ iCurClip.Close();
+ TInt fsError = iFs.Delete( iCurClipFileName );
+ if (fsError != KErrNone)
+ {
+ iMonitor->Error(fsError);
+ return;
+ }
+ iCurClipFileName.Zero();
+ iCurClipDurationList.Reset();
+ iCurClipTimeStampList.Reset();
+ }
+ iMonitor->Error(error);
+ return;
+ }
+
+ }
+ PRINT((_L("CMovieProcessorImpl::FinalizeVideoClip() end")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ProcessAudioL
+// Starts audio processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::ProcessAudioL()
+{
+
+ VPASSERT(iAudioProcessor == 0);
+
+ CVedMovieImp* songmovie = (iMovie);
+ CAudSong* songPointer = songmovie->Song();
+
+ // always read audio decoder specific info from audio engine
+ TAudType audioType = songPointer->OutputFileProperties().iAudioType;
+
+ if( audioType == EAudAAC_MPEG4 )
+ {
+ HBufC8* audioinfo = 0;
+ songPointer->GetMP4DecoderSpecificInfoLC(audioinfo,64);
+
+ if (audioinfo != 0)
+ {
+ CMP4Composer* composeInfo = (CMP4Composer*)iComposer;
+ User::LeaveIfError(composeInfo->WriteAudioSpecificInfo(audioinfo));
+ CleanupStack::Pop();
+ delete audioinfo;
+ audioinfo = 0;
+ }
+
+ }
+ if( (iMovieSizeLimit > 0)&&(iMovieSizeLimitExceeded) )
+ {
+ songPointer->SetDuration(iEndCutTime.Int64()*1000);
+ }
+
+ // create audioprocessor
+ iAudioProcessor = CAudioProcessor::NewL(this, songPointer);
+
+ // start processing
+ iAudioProcessor->StartL();
+
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::AudioProcessingComplete
+// Called by audio processor when audio processing has been completed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::AudioProcessingComplete(TInt aError)
+{
+
+ if (aError != KErrNone)
+ {
+ iMonitor->Error(aError);
+ return;
+ }
+
+ if (iProcessingCancelled)
+ return;
+
+ TInt error = FinalizeAudioWrite();
+ if (error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+
+ iAudioProcessingCompleted = ETrue;
+
+ // since this is run in audio processor's RunL, the audio processor
+ // cannot be deleted here. signal the AO to finish in this->RunL()
+
+ VPASSERT(!IsActive());
+
+ SetActive();
+ iStatus = KRequestPending;
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+
+
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FinalizeVideoSequence
+// Finalizes the movie once all clips have been processed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::FinalizeVideoSequenceL()
+{
+
+ CVedMovieImp* movie = (iMovie);
+
+ // calculate video left-over duration in case audio runs longer than video
+ iLeftOverDuration = 0;
+ if (iNumberOfVideoClips > 0)
+ {
+ iLeftOverDuration = movie->Duration().Int64()/1000 -
+ movie->VideoClip(iNumberOfVideoClips-1)->EndTime().Int64()/1000;
+ }
+ else
+ iLeftOverDuration = movie->Duration().Int64()/1000;
+
+ if ( iLeftOverDuration > 0)
+ {
+ VPASSERT( iNumberOfAudioClips!=0 );
+ // encode black frames
+
+ if(iVideoProcessor)
+ {
+ delete iVideoProcessor;
+ iVideoProcessor = 0;
+ }
+
+ if (!iVideoEncoder)
+ {
+ // create and initialise encoder
+
+ iVideoEncoder = CVideoEncoder::NewL(iMonitor, iAvcEdit, iMovie->VideoCodecMimeType());
+
+ iVideoEncoder->SetFrameSizeL(iMovie->Resolution());
+
+ if ( iMovie->VideoFrameRate() > 0 )
+ iVideoEncoder->SetFrameRate( iMovie->VideoFrameRate() );
+ if ( iMovie->VideoBitrate() > 0 ) // if there is request for restricted bitrate, use it
+ iVideoEncoder->SetBitrate( iMovie->VideoBitrate() );
+ else if ( iMovie->VideoStandardBitrate() > 0 ) // use the given standard bitrate
+ iVideoEncoder->SetBitrate( iMovie->VideoStandardBitrate() );
+
+ // use input framerate of 1 fps
+ iVideoEncoder->SetInputFrameRate(1.0);
+
+ if( iMovie->RandomAccessRate() > 0.0 )
+ iVideoEncoder->SetRandomAccessRate( iMovie->RandomAccessRate() );
+
+ // async.
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+ iVideoEncoder->InitializeL(iStatus);
+
+ iEncoderInitPending = ETrue;
+ iEncodingBlackFrames = ETrue;
+ return;
+
+ }
+ TSize tmpSize = iMovie->Resolution();
+ TUint yLength = tmpSize.iWidth * tmpSize.iHeight;
+ TUint uvLength = yLength >> 1;
+ TUint yuvLength = yLength + uvLength;
+
+ if ( iEncoderBuffer == 0 )
+ {
+ // allocate memory for encoder input YUV frame
+ iEncoderBuffer = (TUint8*)User::AllocL(yuvLength);
+ }
+
+ // fill buffer with 'black' data
+ // Y
+ TPtr8 yuvPtr(0,0);
+ TInt data=5; // don't use zero - real player doesn't show all-zero frames
+ yuvPtr.Set(iEncoderBuffer, yLength, yLength);
+ yuvPtr.Fill((TChar)data, yLength);
+
+ // U,V
+ data=128;
+ yuvPtr.Set(iEncoderBuffer + yLength, uvLength, uvLength);
+ yuvPtr.Fill((TChar)data, uvLength);
+
+ yuvPtr.Set(iEncoderBuffer, yuvLength, yuvLength);
+
+ if (iNumberOfVideoClips == 0)
+ iTimeStamp = 0;
+ else
+ iTimeStamp = movie->VideoClip(iNumberOfVideoClips-1)->CutOutTime();
+
+ if (!IsActive())
+ {
+ SetActive();
+ iStatus = KRequestPending;
+ }
+
+ iVideoEncoder->EncodeFrameL(yuvPtr, iStatus, iTimeStamp);
+ iEncodePending = ETrue;
+
+ return;
+
+ }
+
+ // movie complete, close everything
+
+ User::LeaveIfError(FinalizeVideoWrite());
+
+ // delete all objects except status monitor
+ if (iComposer)
+ {
+ User::LeaveIfError(iComposer->Close());
+ delete iComposer;
+ iComposer = 0;
+ }
+
+ DoCloseVideoL();
+
+ DeleteClipStructures();
+
+ PRINT((_L("CMovieProcessorImpl::FinalizeVideoSequence() - calling completed callback")))
+
+ iMonitor->ProcessingComplete();
+ iState = EStateIdle;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CurrentMetadataSize
+// Get current metadata size
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CMovieProcessorImpl::CurrentMetadataSize()
+{
+ TBool haveAudio;
+ TBool haveVideo;
+ TUint metadatasize = 0;
+
+ haveAudio = EFalse;
+ haveVideo = EFalse;
+
+ if ( GetOutputVideoType() == EVedVideoTypeH263Profile0Level10 ||
+ GetOutputVideoType() == EVedVideoTypeH263Profile0Level45 )
+ {
+ haveVideo = ETrue;
+ metadatasize += 574; // Constant size H.263 metadata
+ metadatasize += (iVideoFrameNumber * 16 + iVideoIntraFrameNumber * 4); // Content dependent H.263 metadata
+ }
+
+ if ( GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile )
+ {
+ haveVideo = ETrue;
+ metadatasize += 596; // Constant size MPEG-4 video metadata
+ metadatasize += (iVideoFrameNumber * 16 + iVideoIntraFrameNumber * 4); // Content dependent MPEG-4 video metadata
+ }
+
+ if ( GetOutputAudioType() == EVedAudioTypeAMR ) // AMR-NB
+ {
+ haveAudio = ETrue;
+ metadatasize += 514; // Constant size AMR metadata
+ metadatasize += ((iAudioFrameNumber + KVedAudioFramesInSample - 1) / KVedAudioFramesInSample) * 8;
+ }
+
+ if ( GetOutputAudioType() == EVedAudioTypeAAC_LC ) // MPEG-4 AAC-LC
+ {
+ haveAudio = ETrue;
+ metadatasize += 514; // Constant size metadata
+ metadatasize += (iAudioFrameNumber * 8);
+ }
+
+ if (haveAudio && haveVideo)
+ metadatasize -= 116; // There is only one moov and mvhd in a file
+
+ return metadatasize;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::BufferAMRFrames
+// Collects output audio frames to a buffer and writes them
+// to the output 3gp file when a whole audio sample is available
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::BufferAMRFrames(const TDesC8& aBuf, TInt aNumFrames,TInt aDuration)
+
+{
+
+ VPASSERT(iOutAudioBuffer);
+ TPtr8 outAudioPtr(iOutAudioBuffer->Des());
+ TInt error = KErrNone;
+
+ if((outAudioPtr.Length() + aBuf.Length()) > outAudioPtr.MaxLength())
+ {
+ // extend buffer size
+
+ // New size is 3/2ths of the old size, rounded up to the next
+ // full kilobyte
+ TUint newSize = (3 * outAudioPtr.MaxLength()) / 2;
+ newSize = (newSize + 1023) & (~1023);
+ TRAP(error, (iOutAudioBuffer = iOutAudioBuffer->ReAllocL(newSize)) );
+
+ if (error != KErrNone)
+ return error;
+
+ PRINT((_L("CMovieProcessorImpl::BufferAMRFrames() - extended buffer to %d bytes"), newSize));
+
+ outAudioPtr.Set(iOutAudioBuffer->Des());
+ }
+ outAudioPtr.Append(aBuf);
+ iTotalDurationInSample += aDuration;
+ iAudioFramesInBuffer += aNumFrames;
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::WriteAMRSamplesToFile
+// Write buffered AMR sample(s) to composer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::WriteAMRSamplesToFile()
+{
+
+ VPASSERT(iOutAudioBuffer);
+ TPtr8 outAudioPtr(iOutAudioBuffer->Des());
+
+ VPASSERT(TUint(iAudioFramesInSample) == KVedAudioFramesInSample);
+
+ while ( iAudioFramesInBuffer >= iAudioFramesInSample )
+ {
+ // write one audio sample to file
+
+// TInt frameSamples = 160;
+// TInt samplingRate = KVedAudioSamplingRate8k;
+ TInt audioSampleDurationInTicks = 0;
+ TPtrC8 writeDes;
+ TInt sampleSize = 0;
+// TInt frameNum = 0;
+// TInt frameSize = 0;
+ TUint8* frameBuffer = (TUint8*)outAudioPtr.Ptr();
+ TInt error = KErrNone;
+
+ // Gets Size of buffer of current frames
+ sampleSize = outAudioPtr.Length();
+
+ // if frame is sampled at a different rate
+ audioSampleDurationInTicks = GetAudioTimeInTicksFromMs(iTotalDurationInSample/1000);
+
+ // set descriptor to sample
+ writeDes.Set( outAudioPtr.Left(sampleSize) );
+
+ // compose audio to output 3gp file
+ error = iComposer->WriteFrames((TDesC8&)writeDes, sampleSize, audioSampleDurationInTicks, 0 /*iAudioKeyFrame*/,
+ iAudioFramesInSample, CMP4Composer::EFrameTypeAudio);
+
+ // Resetting duration to zero
+ iTotalDurationInSample = 0;
+
+ if (error != KErrNone)
+ return error;
+
+ if ( outAudioPtr.Length() > sampleSize )
+ {
+ // copy rest of the data to beginning of buffer
+ frameBuffer = (TUint8*)outAudioPtr.Ptr();
+ TInt len = outAudioPtr.Length() - sampleSize;
+ Mem::Copy(frameBuffer, frameBuffer + sampleSize, len);
+ outAudioPtr.SetLength(len);
+ }
+ else
+ {
+ VPASSERT(iAudioFramesInBuffer == iAudioFramesInSample);
+ outAudioPtr.SetLength(0);
+ }
+
+ iAudioFramesInBuffer -= iAudioFramesInSample;
+ iAudioFrameNumber += iAudioFramesInSample;
+ }
+ return KErrNone;
+
+}
+
+TInt CMovieProcessorImpl::WriteAllAudioFrames(TDesC8& aBuf, TInt aDuration)
+{
+
+ if (iDiskFull)
+ return KErrDiskFull;
+
+ // check available disk space
+
+ TInt error;
+ TInt64 freeSpace = 0;
+ // get free space on disk
+ TRAP(error, freeSpace = iComposer->DriveFreeSpaceL());
+ if (error != KErrNone)
+ return error;
+
+ // subtract metadata length from free space
+ freeSpace -= TInt64(CurrentMetadataSize());
+
+ if (freeSpace < TInt64(KDiskSafetyLimit))
+ {
+ iDiskFull = ETrue;
+ return KErrDiskFull;
+ }
+
+
+ if ( GetOutputAudioType() == EVedAudioTypeAMR )
+ {
+ // write frame by frame until duration >= duration for this clip
+
+ // NOTE: clip duration not checked!!!
+
+ TPtr8 ptr(0,0);
+ TUint8* buf = (TUint8*)aBuf.Ptr();
+ TInt frameSize = aBuf.Length();
+
+ ptr.Set(buf, frameSize, frameSize);
+ error = BufferAMRFrames(ptr, 1,aDuration);
+ if ( error != KErrNone )
+ return error;
+ iTotalAudioTimeWrittenMs += (aDuration/1000); //20;
+ buf += frameSize;
+
+ }
+ else
+ {
+ // write buffer directly to file (1 frame per sample in AAC)
+
+ error = KErrNone;
+// TInt error = KErrNone;
+ TInt sampleSize = aBuf.Length();
+// const TInt framesInSample = 1;
+ TInt audioSampleDurationInTicks = GetAudioTimeInTicksFromMs(aDuration/1000);
+
+ iTotalAudioTimeWrittenMs += (aDuration/1000);
+
+ VPASSERT(iAudioFramesInSample == 1);
+ error = iComposer->WriteFrames(aBuf, sampleSize, audioSampleDurationInTicks, 0 /*iAudioKeyFrame*/,
+ iAudioFramesInSample, CMP4Composer::EFrameTypeAudio);
+ }
+
+ if ( GetOutputAudioType() == EVedAudioTypeAMR )
+ {
+ error = WriteAMRSamplesToFile();
+ if ( error != KErrNone )
+ return error;
+ }
+
+ if ( (iTotalAudioTimeWrittenMs % 200) == 0 )
+ IncProgressBar();
+
+ return KErrNone;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FinalizeAudioWrite
+// Write the remaining audio frames at the end of processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::FinalizeAudioWrite()
+{
+
+ VPASSERT(iAudioFramesInBuffer < iAudioFramesInSample);
+
+ if (iAudioFramesInBuffer == 0)
+ return KErrNone;
+
+ if(iOutputAudioType == EAudioAAC)
+ {
+ // There should not be any frames in buffer !!
+ VPASSERT(0);
+ }
+
+ TInt error = KErrNone;
+ TInt sampleSize = 0;
+// TInt frameNum = 0;
+// TInt frameSize = 0;
+
+ TPtr8 outAudioPtr(iOutAudioBuffer->Des());
+// const TInt frameSamples = 160;
+// const TInt samplingRate = KVedAudioSamplingRate8k;
+
+ TInt audioSampleDurationInTicks = 0;
+ TPtrC8 writeDes;
+ TUint8* frameBuffer = (TUint8*)outAudioPtr.Ptr();
+
+ // Gets Size of buffer of current frames
+ sampleSize = outAudioPtr.Length();
+
+ // if frame is sampled at a different rate
+ audioSampleDurationInTicks = GetAudioTimeInTicksFromMs(iTotalDurationInSample/1000);
+
+ // set descriptor to sample
+ writeDes.Set( outAudioPtr.Left(sampleSize) );
+
+ // compose audio to output 3gp file
+ error = iComposer->WriteFrames((TDesC8&)writeDes, sampleSize, audioSampleDurationInTicks, 0 /*iAudioKeyFrame*/,
+ iAudioFramesInBuffer, CMP4Composer::EFrameTypeAudio);
+
+ iTotalDurationInSample = 0; // resetting the value in sample
+
+ if (error != KErrNone)
+ return error;
+
+ outAudioPtr.SetLength(0);
+ iAudioFrameNumber += iAudioFramesInBuffer;
+ iAudioFramesInBuffer = 0;
+
+
+ return KErrNone;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SetFrameType
+// Sets the frame type (inter/intra) for a frame
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::SetFrameType(TInt aFrameIndex, TUint8 aType)
+{
+ VPASSERT(iFrameParameters);
+ iFrameParameters[aFrameIndex].iType = aType;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoTimeInMsFromTicks
+// Converts a video timestamp from ticks to milliseconds
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt64 CMovieProcessorImpl::GetVideoTimeInMsFromTicks(TInt64 aTimeStampInTicks, TBool aCommonTimeScale) const
+{
+ TUint timeScale = aCommonTimeScale ? iOutputVideoTimeScale : iParser->iStreamParameters.iVideoTimeScale;
+ VPASSERT(timeScale > 0);
+ return TInt64( I64REAL(aTimeStampInTicks) / (TReal)timeScale * 1000 + 0.5 );
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoTimeInTicksFromMs
+// Converts a video timestamp from ms to ticks
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt64 CMovieProcessorImpl::GetVideoTimeInTicksFromMs(TInt64 aTimeStampInMs, TBool aCommonTimeScale) const
+{
+ TUint timeScale = aCommonTimeScale ? iOutputVideoTimeScale : iParser->iStreamParameters.iVideoTimeScale;
+
+ VPASSERT(timeScale > 0);
+
+ return TInt64( I64REAL(aTimeStampInMs) * (TReal)timeScale / 1000 + 0.5 );
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetAudioTimeInMsFromTicks
+// Converts an audio timestamp from ticks to milliseconds
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CMovieProcessorImpl::GetAudioTimeInMsFromTicks(TUint aTimeStampInTicks) const
+{
+
+ TUint timeScale = 0;
+ if(iParser)
+ {
+ timeScale = iParser->iStreamParameters.iAudioTimeScale;
+ }
+ if(timeScale == 0)
+ {
+ //means no audio in clip use output audio timescale itself
+ timeScale = iOutputAudioTimeScale;
+ }
+ VPASSERT(timeScale > 0);
+ return TUint( (TReal)aTimeStampInTicks / (TReal)timeScale * 1000 + 0.5 );
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetAudioTimeInTicksFromMs
+// Converts an audio timestamp from milliseconds to ticks
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CMovieProcessorImpl::GetAudioTimeInTicksFromMs(TUint aTimeStampInMs) const
+
+{
+ return TUint( (TReal)aTimeStampInMs * (TReal)iOutputAudioTimeScale / 1000.0 + 0.5 );
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::WriteVideoFrameToFile
+// Writes a video frame to output 3gp file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::WriteVideoFrameToFile(TDesC8& aBuf, TInt64 aTimeStampInTicks,
+ TInt /*aDurationInTicks*/, TBool aKeyFrame,
+ TBool aCommonTimeScale, TBool aColorTransitionFlag,
+ TBool aFromEncoder)
+{
+
+ //TReal duration = TReal(aDurationInTicks);
+ TBool lessThenZero = false;
+
+ if (iDiskFull)
+ return KErrDiskFull;
+
+ // check available disk space
+
+ TInt64 freeSpace = 0;
+ TInt error;
+ // get free space on disk
+ TRAP(error, freeSpace = iComposer->DriveFreeSpaceL());
+ if (error != KErrNone)
+ return error;
+
+ // subtract metadata length from free space
+ freeSpace -= TInt64(CurrentMetadataSize());
+
+ if (freeSpace < TInt64(KDiskSafetyLimit))
+ {
+ PRINT((_L("CMovieProcessorImpl::WriteVideoFrameToFile() freeSpace below limit")))
+ iDiskFull = ETrue;
+ return KErrDiskFull;
+ }
+
+ // check if we are writing the last frames of the previous
+ // clip while doing crossfade / wipe, iFirstFrameOfClip should
+ // be true when writing the first frame of current clip
+ if ( iCurClipTimeStampList.Count() )
+ {
+ iFirstFrameOfClip = EFalse;
+ if ( aColorTransitionFlag && !iFirstFrameFlagSet )
+ {
+ // this frame is the first one of the second clip
+ iFirstFrameOfClip = ETrue;
+ iFirstFrameFlagSet = ETrue;
+ }
+ }
+
+ TVideoType vt = (TVideoType)iOutputVideoType;
+ // This may be wrong as the files may be of different types so Mp4Specific size may be required to obtained for every file
+ // or every clip but only if it is the first frame
+ if (iVideoFrameNumber == 0 || iFirstFrameOfClip)
+ {
+ if (!iNumberOfVideoClips)
+ {
+ // all clips were either from generator or were black frames
+ if ( iAllGeneratedClips )
+ {
+ iMP4SpecificSize = 0;
+ if (vt == EVideoMPEG4)
+ {
+ iModeChanged = ETrue;
+ iFirstClipUsesEncoder = ETrue;
+ }
+ }
+ else
+ {
+ // black frames; no parser or decoder exists;
+ // no need to modify the vos header by the decoder,
+ // but this forces the composer to search for the VOS header in the 1st frame data
+ iModeChanged = ETrue;
+ }
+ }
+
+ else
+ {
+ // VOS header size is parsed in composer for MPEG-4, in H.263 it is ignored
+ iMP4SpecificSize = 0;
+ }
+ }
+
+ // IMPORTANT: need to make decision here whether to change VosBit
+ // before writing to file, if first frame was encoded
+
+ if (vt == EVideoMPEG4)
+ {
+ if(iVideoFrameNumber == 0)
+ {
+ if(iMpeg4ModeTranscoded)
+ {
+ TBool sBitChanged = EFalse;
+ TRAP(error, sBitChanged = iVideoProcessor->CheckVosHeaderL((TPtrC8&)aBuf));
+ if(sBitChanged) { }
+ PRINT((_L("CMovieProcessorImpl::WritVideoFrameToFile() bit changed: %d"), sBitChanged))
+ if (error != KErrNone)
+ return error;
+ }
+ }
+ }
+
+ TInt currentMetaDataSize = CurrentMetadataSize();
+ TInt64 oldVideoTime = GetVideoTimeInMsFromTicks((TInt64) iCurrentVideoTimeInTicks, ETrue);
+
+ if (iFrameBuffered)
+ {
+ // write buffered frame to file
+
+ TInt64 durationMs = GetVideoTimeInMsFromTicks(aTimeStampInTicks, aCommonTimeScale) - iBufferedTimeStamp;
+
+ if (iWriting1stColorTransitionFrame)
+ {
+ durationMs = i1stColorTransitionFrameTS - iBufferedTimeStamp;
+ iWriting1stColorTransitionFrame = EFalse;
+ }
+
+ else if (iFirstFrameOfClip)
+ {
+ if ( iCurClipTimeStampList.Count() == 0 )
+ {
+ VPASSERT(iVideoClipNumber > 0);
+ CVedMovieImp* movie = reinterpret_cast<CVedMovieImp*>(iMovie);
+ // first frame of new clip
+ durationMs = movie->VideoClip(iVideoClipNumber-1)->CutOutTime().Int64()/1000 - iBufferedTimeStamp;
+ }
+ }
+
+ if (durationMs < 0)
+ {
+ lessThenZero = true;
+ CVedMovieImp* movie = reinterpret_cast<CVedMovieImp*>(iMovie);
+ TReal frameRate = (movie->VideoFrameRate() > 0.0) ? movie->VideoFrameRate() : 15.0;
+ durationMs = TInt64( ( 1000.0 / frameRate ) + 0.5 );
+ }
+
+ if ( iNumberOfVideoClips )
+ {
+ TInt64 clipDuration = iVideoClip->CutOutTime().Int64()/1000 -
+ iVideoClip->CutInTime().Int64()/1000;
+
+ if ( iVideoClipNumber == iNumberOfVideoClips - 1 )
+ {
+ // Add duration of possible black ending frames
+ CVedMovieImp* movie = reinterpret_cast<CVedMovieImp*>(iMovie);
+ clipDuration += ( movie->Duration().Int64()/1000 -
+ movie->VideoClip(iNumberOfVideoClips-1)->EndTime().Int64()/1000 );
+ }
+
+ if ( iVideoClipWritten + durationMs > clipDuration )
+ {
+ durationMs = clipDuration - iVideoClipWritten;
+
+ if ( durationMs <= 0 )
+ {
+ TPtr8 outVideoPtr(iOutVideoBuffer->Des());
+ outVideoPtr.SetLength(0);
+ iFrameBuffered = EFalse;
+ return KErrCompletion;
+ }
+ }
+ }
+
+ TReal duration = I64REAL(durationMs) * TReal(iOutputVideoTimeScale) / 1000.0;
+
+ error = WriteVideoFrameFromBuffer(duration, aColorTransitionFlag);
+
+ if (error != KErrNone)
+ return error;
+ }
+
+ TInt64 currentVideoTime = GetVideoTimeInMsFromTicks((TInt64) iCurrentVideoTimeInTicks, ETrue);
+
+ iCurrentVideoSize += aBuf.Length();
+
+ TInt addAudio = 0;
+ TRAP( error, addAudio = (iMovie->Song())->GetFrameSizeEstimateL(oldVideoTime * 1000, currentVideoTime * 1000) );
+
+ if (error != KErrNone)
+ return error;
+
+ iCurrentAudioSize += addAudio;
+
+ PRINT((_L("CMovieProcessorImpl::WriteVideoFrameToFile() video size: %d, audio size %d, meta data %d"), iCurrentVideoSize, iCurrentAudioSize, currentMetaDataSize))
+
+ if (iMovieSizeLimit > 0 && iCurrentVideoSize + iCurrentAudioSize + currentMetaDataSize > iMovieSizeLimit)
+ {
+ // Cut video here
+ iEndCutTime = TTimeIntervalMicroSeconds(currentVideoTime);
+
+ iMovieSizeLimitExceeded = ETrue;
+
+ // To notify that movie has reached maximum size
+ return KErrCompletion;
+ }
+
+ // Buffer frame
+
+ VPASSERT(iOutVideoBuffer);
+ TPtr8 outVideoPtr(iOutVideoBuffer->Des());
+
+ if((outVideoPtr.Length() + aBuf.Length()) > outVideoPtr.MaxLength())
+ {
+ // extend buffer size
+
+ TUint newSize = outVideoPtr.Length() + aBuf.Length();
+ // round up to the next full kilobyte
+ newSize = (newSize + 1023) & (~1023);
+ TRAP(error, (iOutVideoBuffer = iOutVideoBuffer->ReAllocL(newSize)) );
+
+ if (error != KErrNone)
+ return error;
+
+ PRINT((_L("CMovieProcessorImpl::WriteVideoFrameToFile() - extended buffer to %d bytes"), newSize));
+
+ outVideoPtr.Set(iOutVideoBuffer->Des());
+ }
+ outVideoPtr.Append(aBuf);
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ if (vt == EVideoAVCProfileBaseline)
+ {
+// TBool containsDCR = EFalse;
+// if (!aFromEncoder && iFirstFrameOfClip)
+// containsDCR = ETrue;
+
+ error = iAvcEdit->ParseFrame(iOutVideoBuffer, EFalse, aFromEncoder);
+ if (error != KErrNone)
+ return error;
+ }
+#endif
+
+ if(!lessThenZero)
+ {
+ iBufferedTimeStamp = GetVideoTimeInMsFromTicks(aTimeStampInTicks, aCommonTimeScale);
+ }
+ iBufferedKeyFrame = aKeyFrame;
+ iBufferedFromEncoder = aFromEncoder;
+ iFrameBuffered = ETrue;
+ if ( iFirstFrameOfClip )
+ iFirstFrameBuffered = ETrue;
+
+ iFirstFrameOfClip = EFalse;
+
+ iVideoFrameNumber++;
+
+ if (aKeyFrame)
+ iVideoIntraFrameNumber++;
+
+ return KErrNone;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FinalizeVideoWrite
+// Writes the last video frame from buffer to file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::FinalizeVideoWrite()
+{
+
+ if ( !iFrameBuffered )
+ return KErrNone;
+
+ CVedMovieImp* movie = reinterpret_cast<CVedMovieImp*>(iMovie);
+
+ iApplySlowMotion = EFalse; // this duration must not be scaled
+ TInt64 durationMs = movie->Duration().Int64()/1000 - GetVideoTimeInMsFromTicks(iCurrentVideoTimeInTicks, ETrue);
+ TReal duration = I64REAL(durationMs) * TReal(iOutputVideoTimeScale) / 1000.0;
+
+ TInt error = WriteVideoFrameFromBuffer(duration, EFalse);
+
+ return error;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::FinalizeVideoWrite
+// Writes a frame from buffer to file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::WriteVideoFrameFromBuffer(TReal aDuration, TBool aColorTransitionFlag)
+{
+
+ VPASSERT(iFrameBuffered);
+
+ TReal duration = aDuration;
+
+ // slow motion
+ VPASSERT(iSpeed > 0);
+ const TInt maxSpeed = KMaxVideoSpeed;
+ TReal iScaleFactor = (TReal)maxSpeed/(TReal)iSpeed;
+
+ if( iScaleFactor != 1.0 && iApplySlowMotion )
+ {
+ duration = duration * iScaleFactor;
+ }
+
+ iCurrentVideoTimeInTicks += duration;
+
+ // if the first frame of a clip is being buffered,
+ // we are now writing the last frame of previous clip
+ // so don't increment iVideoClipWritten yet
+
+ // Also take into account crossfade / wipe transition
+ // so that iVideoClipWritten is not incremented
+ // for transition frames of the previous clip
+ if ( !iFirstFrameOfClip && ( (iCurClipTimeStampList.Count() == 0) ||
+ aColorTransitionFlag ) )
+ {
+ iVideoClipWritten += GetVideoTimeInMsFromTicks(aDuration, ETrue);
+ }
+
+ IncProgressBar();
+
+ TVedVideoBitstreamMode currClipMode;
+ TVideoType vt = (TVideoType)iOutputVideoType;
+
+ if (iNumberOfVideoClips > 0)
+ currClipMode = iVideoClip->Info()->TranscodeFactor().iStreamType;
+ else
+ {
+ if ( (vt == EVideoH263Profile0Level10) || (vt == EVideoH263Profile0Level45) )
+ currClipMode = EVedVideoBitstreamModeH263;
+ else
+ currClipMode = EVedVideoBitstreamModeMPEG4Regular;
+ }
+ TPtr8 outVideoPtr(iOutVideoBuffer->Des());
+
+ TInt returnedVal = 0;
+ returnedVal = iComposer->WriteFrames(outVideoPtr, outVideoPtr.Size(), TInt(duration + 0.5),
+ iBufferedKeyFrame, 1 /*numberOfFrames*/,
+ CMP4Composer::EFrameTypeVideo, iMP4SpecificSize,
+ iModeChanged, iFirstFrameBuffered, currClipMode, iBufferedFromEncoder);
+
+ iFirstFrameBuffered = EFalse;
+
+ if (returnedVal == KErrWrite)
+ {
+ // frame was not written
+ iVideoClipWritten -= GetVideoTimeInMsFromTicks(aDuration, ETrue);
+ iCurrentVideoTimeInTicks -= duration;
+ returnedVal = KErrNone;
+ }
+
+ iFrameBuffered = EFalse;
+ outVideoPtr.SetLength(0);
+
+ return returnedVal;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SaveVideoFrameToFile
+// Save a video YUV frame to the tmp file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::SaveVideoFrameToFile(TDesC8& aBuf, TInt aDuration, TInt64 aTimeStamp )
+{
+ TBool isOpen = EFalse;
+ TInt errCode = KErrNone;
+ if ( ( errCode = iFs.IsFileOpen( iNextClipFileName, isOpen ) ) == KErrNone )
+ {
+ if ( isOpen )
+ {
+ if ( ( errCode = iNextClipDurationList.Append( aDuration ) ) == KErrNone )
+ {
+ if ( ( errCode = iNextClipTimeStampList.Append( aTimeStamp ) ) == KErrNone )
+ {
+ if ( iDiskFull )
+ {
+ errCode = KErrDiskFull;
+ }
+ else
+ {
+ TInt64 freeSpace = 0;
+ // get free space on disk
+ TRAP( errCode, freeSpace = iComposer->DriveFreeSpaceL() );
+ if ( errCode == KErrNone )
+ {
+ // subtract yuv length from free space
+ freeSpace -= TInt64( aBuf.Length() );
+
+ if ( freeSpace < TInt64( KDiskSafetyLimit ) )
+ {
+ iDiskFull = ETrue;
+ errCode = KErrDiskFull;
+ }
+ else
+ {
+ errCode = iNextClip.Write( aBuf );
+ iPreviousTimeScale = iParser->iStreamParameters.iVideoTimeScale;
+ }
+ }
+ }
+ if ( errCode != KErrNone )
+ {
+ // rollback the insertion
+ iNextClipDurationList.Remove( iNextClipDurationList.Count() - 1 );
+ iNextClipTimeStampList.Remove( iNextClipTimeStampList.Count() - 1 );
+ }
+ }
+ else
+ {
+ // rollback the insertion
+ iNextClipDurationList.Remove( iNextClipDurationList.Count() - 1 );
+ }
+ }
+ }
+ else
+ {
+ errCode = KErrNotFound;
+ }
+ }
+ return errCode;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoFrameFromFile
+// Retrieve a video YUV frame from the tmp file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetVideoFrameFromFile(TDes8& aBuf, TInt aLength, TInt& aDuration, TInt64& aTimeStamp)
+{
+
+ TBool isOpen = EFalse;
+ TInt errCode = KErrNone;
+ if ( ( errCode = iFs.IsFileOpen( iCurClipFileName, isOpen ) ) == KErrNone )
+ {
+ if ( isOpen )
+ {
+ if ( ( errCode = iCurClip.Read( aBuf, aLength ) ) == KErrNone )
+ {
+ if ( !iTimeStampListScaled )
+ {
+ // change timestamps to start from zero
+ TInt firstTs = iCurClipTimeStampList[0];
+ for ( TInt index = 0; index < iCurClipTimeStampList.Count(); ++index )
+ {
+ iCurClipTimeStampList[index] = iCurClipTimeStampList[index] - firstTs;
+ }
+
+ iOffsetTimeStamp = iCurClipTimeStampList[iCurClipTimeStampList.Count() - 1] +
+ iCurClipDurationList[iCurClipDurationList.Count() - 1];
+ TReal scaleFactor = (TReal)iParser->iStreamParameters.iVideoTimeScale/(TReal)iPreviousTimeScale;
+ iOffsetTimeStamp = TInt( I64REAL(iOffsetTimeStamp) * scaleFactor + 0.5 );
+
+ for ( TInt index = 0; index < iCurClipDurationList.Count(); ++index )
+ {
+ // scale up or scale down
+ iCurClipDurationList[index] = TInt( TReal(iCurClipDurationList[index]) * scaleFactor + 0.5 );
+ iCurClipTimeStampList[index] = TInt64( I64REAL(iCurClipTimeStampList[index]) * scaleFactor + 0.5 );
+ }
+ iTimeStampListScaled = ETrue;
+ }
+
+ if ( iCurClipIndex < iCurClipDurationList.Count() )
+ {
+ aDuration = iCurClipDurationList[iCurClipIndex];
+ aTimeStamp = iCurClipTimeStampList[iCurClipIndex++];
+ }
+ else
+ {
+ aDuration = -1;
+ aTimeStamp = -1;
+ }
+
+ }
+ }
+ else
+ {
+ errCode = KErrNotFound;
+ }
+ }
+ return errCode;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetNextFrameDuration
+// Get the next frame duration and timestamp
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::GetNextFrameDuration(TInt& aDuration, TInt64& aTimeStamp,
+ TInt aIndex, TInt& aTimeStampOffset)
+{
+
+ TInt count = iCurClipTimeStampList.Count();
+
+ if (!iTimeStampListScaled)
+ {
+ // save the timestamp of first color transition frame, so that the duration of
+ // last frame from first clip is calculated correctly in WriteVideoFrameToFile()
+ i1stColorTransitionFrameTS = TInt64( I64REAL(iCurClipTimeStampList[0]) / (TReal)iPreviousTimeScale * 1000 + 0.5 );
+ iWriting1stColorTransitionFrame = ETrue;
+
+ // change timestamps to start from zero
+ TInt firstTs = iCurClipTimeStampList[0];
+ for ( TInt index = 0; index < iCurClipTimeStampList.Count(); ++index )
+ {
+ iCurClipTimeStampList[index] = iCurClipTimeStampList[index] - firstTs;
+ }
+
+ iOffsetTimeStamp = iCurClipTimeStampList[iCurClipTimeStampList.Count() - 1] +
+ iCurClipDurationList[iCurClipDurationList.Count() - 1];
+ TReal scaleFactor = (TReal)iParser->iStreamParameters.iVideoTimeScale/(TReal)iPreviousTimeScale;
+ iOffsetTimeStamp = TInt( I64REAL(iOffsetTimeStamp) * scaleFactor + 0.5 );
+
+ for ( TInt index = 0; index < iCurClipDurationList.Count(); ++index )
+ {
+ // scale up or scale down
+ iCurClipDurationList[index] = TInt( TReal(iCurClipDurationList[index]) * scaleFactor + 0.5 );
+ iCurClipTimeStampList[index] = TInt64( I64REAL(iCurClipTimeStampList[index]) * scaleFactor + 0.5 );
+ }
+ iTimeStampListScaled = ETrue;
+ }
+
+ aTimeStampOffset = iOffsetTimeStamp;
+
+ if (aIndex >= 0)
+ {
+ // just get the values for given index, do not change iCurClipIndex
+ VPASSERT(aIndex < iCurClipDurationList.Count());
+ aDuration = iCurClipDurationList[aIndex];
+ aTimeStamp = iCurClipTimeStampList[aIndex];
+ return;
+ }
+
+ if ( iCurClipIndex < iCurClipDurationList.Count() )
+ {
+ aDuration = iCurClipDurationList[iCurClipIndex];
+ aTimeStamp = iCurClipTimeStampList[iCurClipIndex++];
+ }
+ else
+ {
+ aDuration = 0;
+ aTimeStamp = 0;
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::AppendNextFrameDuration
+// Append the next frame duration and timestamp
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::AppendNextFrameDuration(TInt aDuration, TInt64 aTimeStamp)
+{
+ if ( iCurClipDurationList.Append( aDuration ) == KErrNone )
+ {
+ if ( iCurClipTimeStampList.Append( aTimeStamp + iOffsetTimeStamp ) != KErrNone )
+ {
+ // rollback the insertion
+ iCurClipDurationList.Remove( iCurClipDurationList.Count() - 1 );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetNextClipStartTransitionNumber
+// Get the number of transition at the start of next clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::NextClipStartTransitionNumber()
+{
+ TInt transitionNumber = 5;
+ if ( iMiddleTransitionEffect == EVedMiddleTransitionEffectCrossfade ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeLeftToRight ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeRightToLeft ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeTopToBottom ||
+ iMiddleTransitionEffect == EVedMiddleTransitionEffectWipeBottomToTop )
+ {
+ TInt nextClipNumber = iVideoClipNumber + 1;
+ CVedMovieImp* movie = (iMovie);
+ CVedVideoClip* videoClip = movie->VideoClip(nextClipNumber);
+ CVedVideoClip* origVideoClip = iVideoClip;
+
+ TVedMiddleTransitionEffect middleTransitionEffect = EVedMiddleTransitionEffectNone;
+ if ( iMovie->MiddleTransitionEffectCount() > nextClipNumber )
+ {
+ middleTransitionEffect = iMovie->MiddleTransitionEffect( nextClipNumber );
+ }
+
+ TTimeIntervalMicroSeconds startCutTime = videoClip->CutInTime();
+ TTimeIntervalMicroSeconds endCutTime = videoClip->CutOutTime();
+
+ TInt numberOfFrame = videoClip->Info()->VideoFrameCount();
+
+ // temporary set iVideoClip to next video clip
+ iVideoClip = videoClip;
+
+ TInt startFrameIndex = GetVideoFrameIndex( startCutTime );
+ // the following is because binary search gives us frame with timestamp < startCutTime
+ // this frame would be out of range for movie
+ if ( startFrameIndex > 0 && startFrameIndex < ( numberOfFrame - 1 ) )
+ startFrameIndex++;
+
+ TInt endFrameIndex = GetVideoFrameIndex( endCutTime );
+
+ // determine the total number of included frames in the clip
+ TInt numberOfIncludedFrames = endFrameIndex - startFrameIndex + 1;
+
+ // make sure there are enough frames to apply transition
+ // for transition at both ends
+ if ( middleTransitionEffect != EVedMiddleTransitionEffectNone )
+ {
+ if ( middleTransitionEffect == EVedMiddleTransitionEffectCrossfade ||
+ middleTransitionEffect == EVedMiddleTransitionEffectWipeLeftToRight ||
+ middleTransitionEffect == EVedMiddleTransitionEffectWipeRightToLeft ||
+ middleTransitionEffect == EVedMiddleTransitionEffectWipeTopToBottom ||
+ middleTransitionEffect == EVedMiddleTransitionEffectWipeBottomToTop )
+ {
+ if ( numberOfIncludedFrames < ( transitionNumber << 1 ) )
+ {
+ transitionNumber = numberOfIncludedFrames >> 1;
+ }
+ }
+ else
+ {
+ if ( numberOfIncludedFrames < ( transitionNumber + 10 ) )
+ {
+ if ( ( numberOfIncludedFrames >> 1 ) < transitionNumber )
+ {
+ transitionNumber = numberOfIncludedFrames >> 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( numberOfIncludedFrames < transitionNumber )
+ {
+ transitionNumber = numberOfIncludedFrames;
+ }
+ }
+ // reset iVideoClip back to the original video clip
+ iVideoClip = origVideoClip;
+ }
+ return transitionNumber;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::TransitionDuration
+// Get the transition duration of current clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::TransitionDuration()
+{
+ TInt duration = 0;
+ if ( iNextClipDurationList.Count() )
+ {
+ for ( TInt index = 0; index < iNextClipDurationList.Count() /*- 1*/; index++ )
+ {
+ duration += iNextClipDurationList[index];
+ }
+ }
+ return duration;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::CloseTransitionInfoL
+// Release all internal data hold for transition effect
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::CloseTransitionInfoL()
+{
+ // remove old tmp files
+ if ( iCurClipFileName.Length() )
+ {
+ iCurClip.Close();
+ // it is ok if the tmp file does not exist
+ iFs.Delete( iCurClipFileName );
+ iCurClipFileName.Zero();
+ }
+
+ if ( iNextClipFileName.Length() )
+ {
+ iNextClip.Close();
+ // it is ok if the tmp file does not exist
+ iFs.Delete( iNextClipFileName );
+ iNextClipFileName.Zero();
+ }
+
+ // use file manager to delete all previously
+ // *_nokia_vpi.tmp files
+ CFileMan *fileMan = CFileMan::NewL( iFs );
+ CleanupStack::PushL( fileMan );
+ TParse filepath;
+ filepath.Set( iOutputMovieFileName, NULL, NULL );
+ TFileName filesToDelete = filepath.DriveAndPath();
+ filesToDelete.Append( _L( "*_nokia_vpi.tmp" ) );
+ fileMan->Delete( filesToDelete );
+ CleanupStack::PopAndDestroy( fileMan );
+
+ iCurClipDurationList.Reset();
+ iNextClipDurationList.Reset();
+ iCurClipTimeStampList.Reset();
+ iNextClipTimeStampList.Reset();
+ iCurClipIndex = 0;
+ iPreviousTimeScale = 0;
+ iOffsetTimeStamp = 0;
+
+ // Delete Im_nokia_vpi.tmp
+ TFileName tmpath = TPtrC(KTempFilePath);
+ tmpath.Append( _L("x.3gp") );
+
+ // use file manager to delete all previously
+ CFileMan *tempfileMan = CFileMan::NewL( iFs );
+ CleanupStack::PushL( tempfileMan );
+ TParse tempfilepath;
+ tempfilepath.Set(tmpath, NULL, NULL );
+ TFileName tempfilesToDelete = tempfilepath.DriveAndPath();
+ tempfilesToDelete.Append( _L( "Im_nokia_vpi.tmp" ) );
+ tempfileMan->Delete( tempfilesToDelete,0);
+ CleanupStack::PopAndDestroy( tempfileMan );
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoFrameIndex
+// Gets frame index based on its timestamp
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetVideoFrameIndex(TTimeIntervalMicroSeconds aTime) const
+{
+ __ASSERT_ALWAYS((aTime >= TTimeIntervalMicroSeconds(0)) /*&& (aTime <= iMovie->Duration())*/,
+ TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));
+
+ /* Use binary search to find the right frame. */
+
+ TInt videoFrameCount;
+ if (!iThumbnailInProgress)
+ videoFrameCount = iVideoClip->Info()->VideoFrameCount();
+ else
+ videoFrameCount = iParser->GetNumberOfVideoFrames();
+
+ TInt start = 0;
+ TInt end = videoFrameCount - 1;
+ TInt index = -1;
+ while ( start <= end )
+ {
+ index = start + ((end - start) / 2);
+
+ TTimeIntervalMicroSeconds startTime(0);
+ TTimeIntervalMicroSeconds endTime(0);
+
+ TInt tsInTicks;
+ startTime = TTimeIntervalMicroSeconds( TInt64(iParser->GetVideoFrameStartTime(index, &tsInTicks)) * TInt64(1000) );
+
+ if (index < (videoFrameCount - 1))
+ endTime = TTimeIntervalMicroSeconds( TInt64(iParser->GetVideoFrameStartTime(index + 1, &tsInTicks)) * TInt64(1000) );
+ else
+ {
+ TInt durationMs;
+ iParser->GetVideoDuration(durationMs);
+ endTime = TTimeIntervalMicroSeconds( TInt64(durationMs) * TInt64(1000) );
+ }
+
+ if (index < (videoFrameCount - 1))
+ {
+ endTime = TTimeIntervalMicroSeconds(endTime.Int64() - 1);
+ }
+
+ if (aTime < startTime)
+ {
+ end = index - 1;
+ }
+ else if (aTime > endTime)
+ {
+ start = index + 1;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return index;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::EnhanceThumbnailL
+// Enhances the visual quality of the frame
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::EnhanceThumbnailL(const CFbsBitmap* aInBitmap,
+ CFbsBitmap* aTargetBitmap)
+{
+
+ // create enhancement object
+ if(!iEnhancer)
+ iEnhancer = (CDisplayChain*) CDisplayChain::NewL();
+
+ // enhance image
+ iEnhancer->ProcessL(aInBitmap, aTargetBitmap);
+
+ // clear enhancement object
+ delete iEnhancer;
+ iEnhancer=0;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::NotifyVideoClipGeneratorFrameCompleted
+// The cal back functin called when a frame is to be obtained from the frame generator
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::NotifyVideoClipGeneratorFrameCompleted(CVedVideoClipGenerator& /*aGenerator*/,
+ TInt aError,
+ CFbsBitmap* aFrame)
+{
+
+ if (iProcessingCancelled)
+ {
+ if (aFrame)
+ {
+ delete aFrame; aFrame = 0;
+ }
+ return;
+ }
+
+ if(aError == KErrNone)
+ {
+ CFbsBitmap* aBitmapLocal = aFrame;
+
+ if (aFrame == 0)
+ {
+ iMonitor->Error(KErrArgument);
+ return;
+ }
+
+ VPASSERT(aFrame);
+ TInt error;
+
+ // Convert the frame obtained from bitmap to YUV before giving it to encoder only if error is not there
+ TRAP(error, iImageYuvConverter = CVSFbsBitmapYUV420Converter::NewL(*aBitmapLocal));
+ if (error != KErrNone)
+ {
+ delete aFrame; aFrame = 0; // removed the frame obtained from engine
+ iMonitor->Error(error);
+ return;
+ }
+
+ VPASSERT(iImageYuvConverter);
+
+ TRAP(error, iImageYuvConverter->ProcessL());
+ if (error != KErrNone)
+ {
+ delete aFrame; aFrame = 0; // removed the frame obtained from engine
+ iMonitor->Error(error);
+ return;
+ }
+
+ TRAP(error, iYuvImageBuf = (TUint8*) (TUint8*) HBufC::NewL((iImageYuvConverter->YUVData()).Length()));
+ if(error != KErrNone)
+ {
+ delete aFrame; aFrame = 0; // removed the frame obtained from engine
+ iMonitor->Error(error);
+ return;
+ }
+ iImageSize = (iImageYuvConverter->YUVData()).Length();
+ Mem::Copy(iYuvImageBuf,(iImageYuvConverter->YUVData()).Ptr(),(iImageYuvConverter->YUVData()).Length()); // may be iYUVBuf only
+ iReadImageDes.Set(iYuvImageBuf,iImageSize, iImageSize);
+
+ delete iImageYuvConverter;
+ iImageYuvConverter = 0;
+
+ aBitmapLocal = 0;
+ if(aFrame)
+ {
+ delete aFrame; // removed the frame obtained from engine
+ aFrame = 0;
+ }
+ aBitmapLocal = 0;
+
+ // finished converting to YUV
+ TRAP(error, ProcessImageSetsL(EVideoEncodeFrame)); // EVideoEncodeFrame indicates to encoder to encode and return later
+ if(error != KErrNone)
+ {
+ iMonitor->Error(error);
+ return;
+ }
+ }
+ else
+ {
+ if(aError == KErrCancel)
+ {
+ if(aFrame)
+ {
+ delete aFrame;
+ aFrame =0;
+ }
+
+ if(iImageComposer)
+ {
+ iImageComposer->Close();
+ delete iImageComposer;
+ iImageComposer=0;
+ }
+
+ if (iImageAvcEdit)
+ {
+ delete iImageAvcEdit;
+ iImageAvcEdit = 0;
+ }
+ }
+ else
+ {
+ iMonitor->Error(aError);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetOutputVideoType
+// This function returns the video type of output movie
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TVedVideoType CMovieProcessorImpl::GetOutputVideoType()
+{
+
+ if (iOutputVideoType == EVideoH263Profile0Level10)
+ return EVedVideoTypeH263Profile0Level10;
+
+ if (iOutputVideoType == EVideoH263Profile0Level45)
+ return EVedVideoTypeH263Profile0Level45;
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ if (iOutputVideoType == EVideoAVCProfileBaseline)
+ return EVedVideoTypeAVCBaselineProfile;
+#endif
+
+ if (iOutputVideoType == EVideoMPEG4)
+ return EVedVideoTypeMPEG4SimpleProfile;
+
+ return EVedVideoTypeNoVideo;
+
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetCurrentClipVideoType
+// This function returns the video type of the current video clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TVedVideoType CMovieProcessorImpl::GetCurrentClipVideoType()
+{
+
+ if (!iThumbnailInProgress)
+ {
+
+ CVedMovieImp* movie = reinterpret_cast<CVedMovieImp*>(iMovie);
+
+ CVedVideoClip* currentClip = movie->VideoClip(iVideoClipNumber);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+
+ if (currentInfo->Class() == EVedVideoClipClassGenerated)
+ {
+ switch (iOutputVideoType)
+ {
+ case EVideoH263Profile0Level10:
+ return EVedVideoTypeH263Profile0Level10;
+// break;
+
+ case EVideoH263Profile0Level45:
+ return EVedVideoTypeH263Profile0Level45;
+// break;
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ case EVideoAVCProfileBaseline:
+ return EVedVideoTypeAVCBaselineProfile;
+// break;
+#endif
+
+ case EVideoMPEG4:
+ return EVedVideoTypeMPEG4SimpleProfile;
+// break;
+
+ default:
+ return EVedVideoTypeUnrecognized;
+ }
+ }
+ return currentInfo->VideoType();
+ }
+
+ switch (iParser->iStreamParameters.iVideoFormat)
+ {
+
+ case CParser::EVideoFormatH263Profile0Level10:
+ return EVedVideoTypeH263Profile0Level10;
+// break;
+
+ case CParser::EVideoFormatH263Profile0Level45:
+ return EVedVideoTypeH263Profile0Level45;
+// break;
+
+ case CParser::EVideoFormatMPEG4:
+ return EVedVideoTypeMPEG4SimpleProfile;
+// break;
+
+ case CParser::EVideoFormatAVCProfileBaseline:
+ return EVedVideoTypeAVCBaselineProfile;
+// break;
+
+ default:
+ return EVedVideoTypeUnrecognized;
+ }
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoClipTranscodeFactor Added for transcoding reqs
+// This function returns the mode of the clip indicated by the location aNum
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TVedTranscodeFactor CMovieProcessorImpl::GetVideoClipTranscodeFactor(TInt aNum)
+{
+ CVedVideoClipInfo* curInfo = NULL;
+
+ if(iMovie)
+ {
+ CVedMovieImp* tmovie = (iMovie);
+ CVedVideoClip* currentClip = tmovie->VideoClip(aNum);
+ CVedVideoClipInfo* currentInfo = currentClip->Info();
+ curInfo = currentInfo;
+ }
+ else
+ {
+ // this means there is no movie, which can happen in case of thumb generation as processor does not have it
+ User::Panic(_L("CMovieProcessorImpl MoviePtr is Missing in VideoProcessor"), -1);
+ }
+
+ return curInfo->TranscodeFactor();
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoClipResolution
+// Panics the program on error
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TSize CMovieProcessorImpl::GetVideoClipResolution()
+{
+ return iVideoClip->Info()->Resolution();
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieResolution
+// Gets target movie resolution
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TSize CMovieProcessorImpl::GetMovieResolution()
+{
+ if(iMovie)
+ {
+ return iMovie->Resolution();
+ }
+ else
+ {
+ TSize stdres(KVedMaxVideoWidth, KVedMaxVideoHeight);
+ return stdres;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetVideoClipFrameRate
+// Gets video frame rate of current clip
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TReal CMovieProcessorImpl::GetVideoClipFrameRate()
+ {
+
+ TReal rate;
+ iParser->GetVideoFrameRate(rate);
+
+ return rate;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieFrameRate
+// Gets target movie frame rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TReal CMovieProcessorImpl::GetMovieFrameRate()
+ {
+ return iMovie->VideoFrameRate();
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieVideoBitrate
+// Gets target movie video bit rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetMovieVideoBitrate()
+ {
+ return iMovie->VideoBitrate();
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieVideoBitrate
+// Gets standard movie video bit rate (mandated by standard for used video codec)
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetMovieStandardVideoBitrate()
+ {
+ return iMovie->VideoStandardBitrate();
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetMovieAudioBitrate
+// Gets target movie audio bit rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetMovieAudioBitrate()
+ {
+ return iMovie->AudioBitrate();
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetSyncIntervalInPicture
+// Gets sync interval in picture
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetSyncIntervalInPicture()
+ {
+ if ( iMovie )
+ {
+ return iMovie->SyncIntervalInPicture();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetRandomAccessRate
+// Get random access rate setting
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TReal CMovieProcessorImpl::GetRandomAccessRate()
+ {
+ if ( iMovie )
+ {
+ return iMovie->RandomAccessRate();
+ }
+ else
+ {
+ return 0.2;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetOutputAudioType() Added for AAC support
+// This function returns the audio type of the final movie which will be created
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TVedAudioType CMovieProcessorImpl::GetOutputAudioType() //added for AAC support
+{
+ return DecideAudioType(iOutputAudioType);
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::DecideAudioType(TAudioType aAudioType) added for AAC support
+// This function returns the audio type depending on the parameter sent
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TVedAudioType CMovieProcessorImpl::DecideAudioType(TAudioType aAudioType) //added for AAC support
+{
+ if( aAudioType == (TAudioType)EAudioAMR)
+ {
+ return EVedAudioTypeAMR;
+ }
+ else if(aAudioType == (TAudioType)EAudioAAC)
+ {
+ // changed EVedAudioTypeAAC_LC --> EVedAudioTypeAAC_LC --Sami
+ return EVedAudioTypeAAC_LC;
+ }
+ else if(aAudioType == (TAudioType)EAudioNone)
+ {
+ return EVedAudioTypeNoAudio;
+ }
+ else
+ {
+ return EVedAudioTypeUnrecognized;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SetMovieSizeLimit
+// Sets the maximum size for the movie
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMovieProcessorImpl::SetMovieSizeLimit(TInt aLimit)
+{
+ // reserve 2000 bytes for safety margin, since size is checked after a video frame is written to file.
+ iMovieSizeLimit = (aLimit - 2000 > 0) ? aLimit - 2000 : 0;
+}
+
+
+//==================================
+// color tone RGB TO YUV Function
+//==================================
+
+void CMovieProcessorImpl::ConvertColorToneRGBToYUV(TVedColorEffect aColorEffect,TRgb aColorToneRgb)
+{
+ TInt uVal, vVal; // to get the U,V Values of the ColorTone
+
+ CVedVideoClipInfo* currentInfo = iVideoClip->Info();
+ TVedVideoBitstreamMode streamMode = currentInfo->TranscodeFactor().iStreamType;
+
+ // evaluate the u,v values for color toning
+ if (aColorEffect == EVedColorEffectToning)
+ {
+ uVal = TInt(-(0.16875*aColorToneRgb.Red()) - (0.33126*aColorToneRgb.Green()) + (0.5*aColorToneRgb.Blue()) + 0.5);
+ vVal = TInt((0.5*aColorToneRgb.Red()) - (0.41869*aColorToneRgb.Green()) - (0.08131*aColorToneRgb.Blue()) + 0.5);
+ }
+
+ // adjust the u,v values for h.263 and mpeg-4
+ if(iOutputVideoType == EVideoH263Profile0Level10 || iOutputVideoType == EVideoH263Profile0Level45 || (!(iOutputVideoType == EVideoMPEG4) && streamMode == EVedVideoBitstreamModeMPEG4ShortHeader))
+ {
+ if(aColorEffect == EVedColorEffectBlackAndWhite)
+ {
+ uVal = 255; // codeword for value=128
+ vVal = 255; // codeword for value=128
+ }
+ else if (aColorEffect == EVedColorEffectToning)
+ {
+ uVal += 128;
+ vVal += 128;
+
+ AdjustH263UV(uVal);
+ AdjustH263UV(vVal);
+ }
+ }
+ else if (iOutputVideoType == EVideoMPEG4)
+ {
+ if(aColorEffect == EVedColorEffectBlackAndWhite)
+ {
+ uVal = 0; // codeword for value=128
+ vVal = 0; // codeword for value=128
+ }
+ else if (aColorEffect == EVedColorEffectToning)
+ {
+ uVal /= 2; // do not use bit shift; may have negative values
+ vVal /= 2; // do not use bit shift; may have negative values
+ }
+ }
+
+ iColorToneU = uVal;
+ iColorToneV = vVal;
+// iMovie->VideoClipSetColorTone(0, iColorToneYUV);
+
+}
+
+//=======================================
+// CMovieProcessorImpl::AdjustH263UV()
+// Adjusts the UV values for Color Toning
+//=======================================
+void CMovieProcessorImpl::AdjustH263UV(TInt& aValue)
+{
+ if(aValue == 0) // end points are not used
+ {
+ aValue = 1;
+ }
+ else if (aValue == 128) // not used
+ {
+ aValue = 255;
+ }
+ else if (aValue >= 255) // end points are not used
+ {
+ aValue = 254;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetOutputVideoMimeType
+// Return Mime type for output video codec
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC8& CMovieProcessorImpl::GetOutputVideoMimeType()
+{
+ VPASSERT(iMovie);
+
+ return iMovie->VideoCodecMimeType();
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::GetOutputAVCLevel
+// Get output AVC level
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::GetOutputAVCLevel()
+{
+
+ VPASSERT( iOutputVideoType == EVideoAVCProfileBaseline );
+
+ const TPtrC8& mimeType = iMovie->VideoCodecMimeType();
+
+ if ( mimeType.MatchF( _L8("*profile-level-id=42800A*") ) != KErrNotFound )
+ {
+ // baseline profile level 1
+ return 10;
+ }
+
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound )
+ {
+ // baseline profile level 1b
+ return 101; // internal constant for level 1b
+ }
+
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound )
+ {
+ // baseline profile level 1.1
+ return 11;
+ }
+
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42800C*") ) != KErrNotFound )
+ {
+ // baseline profile level 1.2
+ return 12;
+ }
+ //WVGA task
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42800D*") ) != KErrNotFound )
+ {
+ // baseline profile level 1.3
+ return 13;
+ }
+ else if ( mimeType.MatchF( _L8("*profile-level-id=428014*") ) != KErrNotFound )
+ {
+ // baseline profile level 2
+ return 20;
+ }
+ else if ( mimeType.MatchF( _L8("*profile-level-id=428015*") ) != KErrNotFound )
+ {
+ // baseline profile level 2.1
+ return 21;
+ }
+ else if ( mimeType.MatchF( _L8("*profile-level-id=428016*") ) != KErrNotFound )
+ {
+ // baseline profile level 2.2
+ return 22;
+ }
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42801E*") ) != KErrNotFound )
+ {
+ // baseline profile level 3
+ return 30;
+ }
+ else if ( mimeType.MatchF( _L8("*profile-level-id=42801F*") ) != KErrNotFound )
+ {
+ // baseline profile level 3.1
+ return 31;
+ }
+
+ else if ( mimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
+ {
+ // no other profile-level ids supported
+ User::Panic(_L("CMovieProcessorImpl"), EInvalidInternalState);
+ }
+
+ else
+ {
+ // Default is level 1 (?)
+ return 10;
+ }
+ return 10;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::SuspendProcessing
+// Suspends processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::SuspendProcessing()
+{
+
+ PRINT((_L("CMovieProcessorImpl::SuspendProcessing()")));
+
+ iDemux->Stop();
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::ResumeProcessing
+// Resumes processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMovieProcessorImpl::ResumeProcessing(TInt& aStartFrameIndex, TInt aFrameNumber)
+{
+
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), frame number = %d"), aFrameNumber));
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), start index = %d"), iStartFrameIndex ));
+
+ // get index of last written frame
+ TInt index = iStartFrameIndex + aFrameNumber;
+
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), index is %d"), index));
+
+ TInt ticks;
+ // get start time for next frame
+ TInt time = iParser->GetVideoFrameStartTime(index + 1, &ticks);
+ if ( time < 0 )
+ {
+ // time represents an error code from parser
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), error from iParser %d"), time));
+ return time;
+ }
+
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), start frame time = %d ms"), time));
+ iStartCutTime = TTimeIntervalMicroSeconds(TInt64(time) * TInt64(1000));
+
+ // reset parser variables
+ iParser->Reset();
+
+ // seek to Intra from where to start decoding to resume processing
+ TInt error = iParser->SeekOptimalIntraFrame(iStartCutTime, 0, EFalse);
+
+ if (error != KErrNone)
+ return error;
+
+ aStartFrameIndex = iParser->GetStartFrameIndex();
+
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), aStartFrameIndex = %d"), aStartFrameIndex));
+
+ // iStartFrameIndex contains the index of the first included
+ // frame, which is != 0 in case the clip is cut from beginning
+ aStartFrameIndex -= iStartFrameIndex;
+
+ PRINT((_L("CMovieProcessorImpl::ResumeProcessing(), aStartFrameIndex = %d"), aStartFrameIndex));
+
+ iVideoQueue->ResetStreamEnd();
+ iDemux->Start();
+
+ return KErrNone;
+}
+
+// -----------------------------------------------------------------------------
+// CMovieProcessorImpl::NeedTranscoderAnyMore
+// Check if all video is processed already
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CMovieProcessorImpl::NeedTranscoderAnyMore()
+ {
+ PRINT((_L("CMovieProcessorImpl::NeedTranscoderAnyMore()")));
+ if ( iAllVideoProcessed )
+ {
+ PRINT((_L("CMovieProcessorImpl::NeedTranscoderAnyMore() EFalse")));
+ return EFalse;
+ }
+ else
+ {
+ PRINT((_L("CMovieProcessorImpl::NeedTranscoderAnyMore() ETrue")));
+ return ETrue;
+ }
+
+
+ }
+
+
+// OTHER EXPORTED FUNCTIONS
+
+
+//=============================================================================
+
+
+// End of File
+