videoeditorengine/vedengine/videoprocessor/src/VideoEncoderMDF.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/vedengine/videoprocessor/src/VideoEncoderMDF.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,1285 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:  
+* Implementation for video encoder.
+*
+*/
+
+
+#include "statusmonitor.h"
+#include "videoencoder.h"
+#include "vedvideosettings.h"
+#include "vedvolreader.h"
+#include "vedavcedit.h"
+
+
+// Assertion macro wrapper for code cleanup
+#define VEASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CVIDEOENCODER"), EInternalAssertionFailure)) 
+
+// Debug print macro
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x
+#else
+#define PRINT(x)
+#endif
+
+// Constants
+
+
+// time increment resolution
+const TUint KTimeIncrementResolutionHW = 30000;
+//const TUint KTimeIncrementResolutionSW = 29;
+
+const TReal KMinRandomAccessRate = 0.2;
+//const TUint KPictureQuality = 50;
+//const TReal KLatencyQyalityTradeoff = 1.0;
+//const TReal KQualityTemporalTradeoff = 0.8;
+//const TBool KEncodingRealTime = EFalse;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CVideoEncoder::NewL
+// Two-phased constructor.
+// ---------------------------------------------------------
+//
+
+CVideoEncoder* CVideoEncoder::NewL(CStatusMonitor *aMonitor, CVedAVCEdit* aAvcEdit, 
+                                   const TPtrC8& aVideoMimeType)
+{
+	PRINT((_L("CVideoEncoder::NewL() : MDF"))); 
+	
+	CVideoEncoder* self = new (ELeave) CVideoEncoder();    
+	CleanupStack::PushL( self );
+	self->ConstructL(aMonitor, aAvcEdit, aVideoMimeType);
+	CleanupStack::Pop();
+	
+	return self;    
+}
+
+
+CVideoEncoder::CVideoEncoder() : CActive(EPriorityStandard), iInputBuffer(0,0)
+{    
+    iPreviousTimeStamp = TTimeIntervalMicroSeconds(0);
+    iKeyFrame = EFalse;
+}
+
+
+void CVideoEncoder::ConstructL(CStatusMonitor *aMonitor, CVedAVCEdit* aAvcEdit, 
+                               const TPtrC8& aVideoMimeType)
+{
+	iTranscoder = NULL;	
+	iMonitor = aMonitor;
+	iAvcEdit = aAvcEdit;
+
+	iFrameSize = KVedResolutionQCIF;
+	iFrameRate = 15.0;	
+	iInputFrameRate = 15.0;
+	iRandomAccessRate = KMinRandomAccessRate;
+
+    // interpret and store video codec MIME-type. Allocates also iDataBuffer
+    SetVideoCodecL( aVideoMimeType );	
+
+	iStatus = NULL;	
+	
+	iVolReader = CVedVolReader::NewL();
+	
+	// allocate input picture
+	iInputPicture = new (ELeave) TTRVideoPicture;
+	
+	// Create a timer 
+	User::LeaveIfError(iTimer.CreateLocal());
+	iTimerCreated = ETrue;
+	
+	// Add us to active scheduler
+	CActiveScheduler::Add(this);
+}
+
+
+// ---------------------------------------------------------
+// CVideoEncoder::~CVideoEncoder()
+// Destructor
+// ---------------------------------------------------------
+//
+CVideoEncoder::~CVideoEncoder()
+    {
+
+    Cancel();
+
+    if ( iInputPicture )
+	{
+        delete iInputPicture;
+		iInputPicture = 0;
+	}
+	
+	if ( iDataBuffer )
+	{	        
+	    delete iDataBuffer;
+	    iDataBuffer = 0;
+	}
+	
+    if ( iTranscoder )
+	{
+        delete iTranscoder;
+		iTranscoder = 0;
+	}
+	
+	if ( iVolReader )
+	{
+	    delete iVolReader;
+	    iVolReader = 0;
+	}
+    
+    if ( iTimerCreated )
+	{
+        iTimer.Close();
+		iTimerCreated = EFalse;
+	}
+
+
+    }
+
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetVideoCodecL()
+// Interpret and store video mime type
+// ---------------------------------------------------------
+//
+void CVideoEncoder::SetVideoCodecL(const TPtrC8& aMimeType)
+    {
+    TBuf8<256> string;
+    TBuf8<256> newMimeType;
+    string = KVedMimeTypeH263;
+    string += _L8( "*" );
+	TInt dataBufferSize = KMaxCodedPictureSizeQCIF;
+
+    iMaxFrameRate = 15.0;
+    iArbitrarySizeAllowed = EFalse;
+    
+    if ( aMimeType.MatchF( (const TDesC8& )string ) != KErrNotFound ) 
+        {
+        // H.263
+
+        newMimeType = KVedMimeTypeH263;
+
+        if ( aMimeType.MatchF( _L8("*profile*") ) != KErrNotFound )
+            {
+            // profile given, check if we support it
+            if ( aMimeType.MatchF( _L8("*profile=0*")) != KErrNotFound )
+                {
+                // profile 0 requested
+                newMimeType += _L8( "; profile=0" );
+                }
+            else
+                {
+                // no other profiles supported
+                PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported profile")));
+                User::Leave(KErrNotSupported);
+                }
+            }
+        else
+            {
+            // no profile is given => assume 0
+            newMimeType += _L8( "; profile=0" );
+            }
+
+        if ( aMimeType.MatchF( _L8("*level=10*") ) != KErrNotFound )
+            {
+    		iMaxBitRate = iBitRate = KVedBitRateH263Level10;
+    		iMaxResolution = KVedResolutionQCIF;
+    		dataBufferSize = KMaxCodedPictureSizeQCIF;
+            newMimeType += _L8( "; level=10" );
+            }
+        else if ( aMimeType.MatchF( _L8("*level=45*") ) != KErrNotFound )
+            {
+    		iMaxBitRate = iBitRate = KVedBitRateH263Level45;
+    		iMaxResolution = KVedResolutionQCIF;
+    		dataBufferSize = KMaxCodedPictureSizeQCIF;
+            newMimeType += _L8( "; level=45" );
+            }
+        else if ( aMimeType.MatchF( _L8("*level*") ) != KErrNotFound )
+            {
+            // no other levels supported
+            PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported level")));
+            User::Leave(KErrNotSupported);
+            }
+        else
+            {
+            // if no level is given assume 10
+    		iMaxBitRate = iBitRate = KVedBitRateH263Level10;
+    		iMaxResolution = KVedResolutionQCIF;
+    		dataBufferSize = KMaxCodedPictureSizeQCIF;
+            newMimeType += _L8( "; level=10" );
+            }
+        }
+    else
+        {
+        string = KVedMimeTypeMPEG4Visual;
+        string += _L8( "*" );
+
+        if ( aMimeType.MatchF( string ) != KErrNotFound ) 
+            {
+            // MPEG-4 Visual
+            newMimeType = KVedMimeTypeMPEG4Visual;
+            if ( aMimeType.MatchF( _L8("*profile-level-id=8*") ) != KErrNotFound )
+                {
+                // simple profile level 0
+        		iMaxBitRate = iBitRate = KVedBitRateMPEG4Level0;
+        		iMaxResolution = KVedResolutionQCIF;
+                // define max size 10K
+                dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
+                newMimeType += _L8("; profile-level-id=8");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=9*") ) != KErrNotFound )
+                {
+                // simple profile level 0b
+        		iMaxBitRate = iBitRate = KVedBitRateMPEG4Level0;
+        		iMaxResolution = KVedResolutionQCIF;
+                // define max size 10K
+                dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
+                newMimeType += _L8("; profile-level-id=9");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=1*") ) != KErrNotFound )
+                {
+                // simple profile level 1
+        		iMaxBitRate = iBitRate = KVedBitRateMPEG4Level0;
+        		iMaxResolution = KVedResolutionQCIF;
+                // define max size 10K
+                dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
+                iArbitrarySizeAllowed = ETrue;                
+                newMimeType += _L8("; profile-level-id=1");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=2*") ) != KErrNotFound )
+                {
+                // simple profile level 2
+			    dataBufferSize = KMaxCodedPictureSizeMPEG4CIF;
+        		iMaxResolution = KVedResolutionCIF;
+			    iMaxBitRate = iBitRate = KVedBitRateMPEG4Level2;
+                iArbitrarySizeAllowed = ETrue;                
+                newMimeType += _L8("; profile-level-id=2");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=3*") ) != KErrNotFound )
+                {
+                // simple profile level 3
+			    dataBufferSize = KMaxCodedPictureSizeMPEG4CIF;
+			    iMaxBitRate = iBitRate = KVedBitRateMPEG4Level2;
+        		iMaxResolution = KVedResolutionCIF;
+			    iMaxFrameRate = 30.0;
+                iArbitrarySizeAllowed = ETrue;                
+                newMimeType += _L8("; profile-level-id=3");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=4*") ) != KErrNotFound )
+                {
+                // simple profile level 4a
+			    iMaxBitRate = iBitRate = KVedBitRateMPEG4Level4A;	        	
+			    dataBufferSize = KMaxCodedPictureSizeVGA;
+        		iMaxResolution = KVedResolutionVGA;
+			    iMaxFrameRate = 30.0;
+                iArbitrarySizeAllowed = ETrue;                
+                newMimeType += _L8("; profile-level-id=4");
+                }
+            else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
+                {
+                // no other profile-level ids supported
+                PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported MPEG-4 profile-level")));
+                User::Leave(KErrNotSupported);
+                }
+            else
+                {
+                // Default is level 0 in our case (normally probably level 1)
+        		iMaxBitRate = iBitRate = KVedBitRateMPEG4Level0;
+        		iMaxResolution = KVedResolutionQCIF;
+                // define max size 10K
+                dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
+                newMimeType += _L8("; profile-level-id=8");
+                }
+            }
+        else
+            {
+             
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+            string = KVedMimeTypeAVC;
+            string += _L8( "*" );                
+            if ( aMimeType.MatchF( string ) != KErrNotFound ) 
+                {
+                // AVC
+                newMimeType = KVedMimeTypeAVC;
+                if ( aMimeType.MatchF( _L8("*profile-level-id=42800A*") ) != KErrNotFound )
+                    {
+                    // baseline profile level 1
+            		iMaxBitRate = iBitRate = KVedBitRateAVCLevel1;
+            		iMaxResolution = KVedResolutionQCIF;                        
+                    dataBufferSize = KMaxCodedPictureSizeAVCLevel1;
+                    iArbitrarySizeAllowed = ETrue;                
+                    newMimeType += _L8("; profile-level-id=42800A");
+                    }                    
+                else if ( aMimeType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound )
+                    {                                                
+                    // baseline profile level 1b
+                    iMaxBitRate = iBitRate = KVedBitRateAVCLevel1b;
+            		iMaxResolution = KVedResolutionQCIF;                        
+                    dataBufferSize = KMaxCodedPictureSizeAVCLevel1B;
+                    iArbitrarySizeAllowed = ETrue;                
+                    newMimeType += _L8("; profile-level-id=42900B");
+                    }
+                else if ( aMimeType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound )
+                    {
+                    // baseline profile level 1.1
+                    iMaxBitRate = iBitRate = KVedBitRateAVCLevel1_1;
+            		iMaxResolution = KVedResolutionCIF;                        
+                    dataBufferSize = KMaxCodedPictureSizeAVCLevel1_1;
+                    iArbitrarySizeAllowed = ETrue;                
+                    newMimeType += _L8("; profile-level-id=42800B");
+                    }
+                else if ( aMimeType.MatchF( _L8("*profile-level-id=42800C*") ) != KErrNotFound )
+                    {
+                    // baseline profile level 1.2
+                    iMaxBitRate = iBitRate = KVedBitRateAVCLevel1_2;
+            		iMaxResolution = KVedResolutionCIF;                        
+                    dataBufferSize = KMaxCodedPictureSizeAVCLevel1_2;
+                    iArbitrarySizeAllowed = ETrue;                
+                    newMimeType += _L8("; profile-level-id=42800C");                    
+                    }      
+                //WVGA task
+                else if ( aMimeType.MatchF( _L8("*profile-level-id=42801F*") ) != KErrNotFound )
+                    {
+                    // baseline profile level 1.3
+                    iMaxBitRate = iBitRate = KVedBitRateAVCLevel3_1;
+            		iMaxResolution = KVedResolutionWVGA;                        
+                    dataBufferSize = KMaxCodedPictureSizeAVCLevel3_1;
+                    iArbitrarySizeAllowed = ETrue;                
+                    newMimeType += _L8("; profile-level-id=42801F");                    
+                    }
+                else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
+                    {
+                    // no other profile-level ids supported
+                    PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported AVC profile-level")));
+                    User::Leave(KErrNotSupported);
+                    }
+                else
+                    {
+                        // Default is level 1 (?)
+                        iMaxBitRate = iBitRate = KVedBitRateAVCLevel1;
+                		iMaxResolution = KVedResolutionQCIF;                            
+                        dataBufferSize = KMaxCodedPictureSizeAVCLevel1;
+                        newMimeType += _L8("; profile-level-id=42800A");
+                    }                
+                }
+            else
+                {
+                    // unknown mimetype
+                    User::Leave( KErrNotSupported );
+                }                                        
+#else
+                    // unknown mimetype
+                    User::Leave( KErrNotSupported );
+#endif
+            }
+        }
+
+    // successfully interpreted the input mime type
+    iMimeType = newMimeType;
+    if ( iDataBuffer )
+        {
+        delete iDataBuffer;
+        iDataBuffer = NULL;
+        }
+	iDataBuffer = (HBufC8*) HBufC8::NewL(dataBufferSize);    
+
+    }
+    
+// ---------------------------------------------------------
+// CVideoEncoder::SetFrameSizeL
+// Sets the used frame size
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::SetFrameSizeL(const TSize& aSize)
+    {
+  
+    if (iFrameSize == aSize)
+        return;
+
+    if ( (aSize.iWidth > iMaxResolution.iWidth) || (aSize.iHeight > iMaxResolution.iHeight))
+        {
+        if ( iArbitrarySizeAllowed ) // This is for future-proofness. Currently the checking of standard sizes below overrules this one
+            {
+            if ( aSize.iWidth * aSize.iHeight > iMaxResolution.iWidth*iMaxResolution.iHeight )
+                {
+                PRINT((_L("CVideoEncoder::SetFrameSizeL() too high resolution requested")));
+                User::Leave( KErrNotSupported );
+                }
+            }
+        else
+            {
+            PRINT((_L("CVideoEncoder::SetFrameSizeL() incompatible or too high resolution requested")));
+            User::Leave( KErrNotSupported );
+            }
+        }
+    
+	// check new size. For now only standard sizes are allowed
+	if ( (aSize != KVedResolutionSubQCIF) && 
+		 (aSize != KVedResolutionQCIF) &&
+		 (aSize != KVedResolutionCIF) &&
+		 (aSize != KVedResolutionQVGA) &&
+		 (aSize != KVedResolutionVGA16By9) &&
+		 (aSize != KVedResolutionVGA) &&
+		 //WVGA task
+		 (aSize != KVedResolutionWVGA) )
+	{
+		 User::Leave( KErrArgument );
+	}
+
+    iFrameSize = aSize;    
+    
+    }
+
+// ---------------------------------------------------------
+// CVideoEncoder::GetFrameSize
+// Gets the used frame size
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::FrameSize(TSize& aSize) const
+    {
+
+    aSize = iFrameSize;
+
+    }
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetFrameRate
+// Sets the used targt frame rate
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVideoEncoder::SetFrameRate(const TReal aFrameRate)
+{
+    VEASSERT(aFrameRate > 0.0);
+
+    if ( aFrameRate <= iMaxFrameRate )
+        {
+        iFrameRate = TReal32(aFrameRate);
+        }
+    else
+        {
+        iFrameRate = iMaxFrameRate;
+        }
+        
+    // target framerate cannot be larger than source framerate
+    if (iFrameRate > iInputFrameRate)
+        iFrameRate = iInputFrameRate;
+
+    return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetInputFrameRate
+// Sets the used input sequence frame rate
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVideoEncoder::SetInputFrameRate(const TReal aFrameRate)
+    {
+    
+    VEASSERT(aFrameRate > 0.0);
+         
+    iInputFrameRate = aFrameRate;
+        
+    // target framerate cannot be larger than source framerate
+    if (iFrameRate > iInputFrameRate)
+        iFrameRate = iInputFrameRate;
+    
+    return KErrNone;
+        
+    }
+
+    
+// ---------------------------------------------------------
+// CVideoEncoder::SetRandomAccessRate
+// Sets the used target random access rate
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVideoEncoder::SetRandomAccessRate(const TReal aRate)
+{
+    VEASSERT(aRate > 0.0);
+
+    iRandomAccessRate = aRate;
+
+    return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetBitrate
+// Sets the used target bitrate
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVideoEncoder::SetBitrate(const TInt aBitrate)
+{    
+    VEASSERT(aBitrate > 0);
+
+    if ( aBitrate <= iMaxBitRate )
+        {
+        iBitRate = aBitrate;
+        }
+    else
+        {
+        iBitRate = iMaxBitRate;
+        }
+
+    return KErrNone;
+
+}
+
+// --------------------------------------------------------
+
+
+
+// ---------------------------------------------------------
+// CVideoEncoder::InitializeL
+// Initializes the encoder
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::InitializeL(TRequestStatus &aStatus)
+    {
+    
+    PRINT((_L("CVideoEncoder::InitializeL() in")));
+
+    iResetRequestStatus = &aStatus;
+
+    // Create DevVideoRecord & select video encoder
+
+    if ( iTranscoder ) 
+        {
+        // need to recreate since parameters changed
+        delete iTranscoder;
+        iTranscoder = 0;
+        }
+
+    iFatalError = EFalse;
+
+    iTranscoder = CTRTranscoder::NewL(*this);
+
+    // Select & set parameters to transcoder    
+    TRAPD(err, SetupEncoderL());
+        
+    if ( err != KErrNone )
+        {
+        // error
+        User::Leave( err );
+        }
+    
+    iTranscoder->InitializeL();
+    
+    PRINT((_L("CVideoEncoder::InitializeL() out")));
+    
+
+    }
+
+// ---------------------------------------------------------
+// CVideoEncoder::Start
+// Starts the encoder
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+
+void CVideoEncoder::Start()
+{
+    TRAPD( error, iTranscoder->StartL() );
+    
+    if (error != KErrNone)
+        {
+        if (iMonitor)
+            iMonitor->Error(error);
+        }
+}
+
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetRandomAccessPoint
+// Forces the next encoded frame to Intra
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::SetRandomAccessPoint()
+{
+    VEASSERT(iTranscoder);
+    
+    iTranscoder->SetRandomAccessPoint();
+       
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::Stop
+// Stops the encoder
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::Stop()
+{
+	
+    if ( !iFatalError )
+        {
+        
+        if (iStarted)
+            {
+            TRAPD( error, iTranscoder->StopL() );
+            if (error != KErrNone)
+                {
+                if (iMonitor)
+                    iMonitor->Error(error);
+                }
+            }
+        
+        iStarted = EFalse;
+        }
+}
+	
+
+// ---------------------------------------------------------
+// CVideoEncoder::Reset
+// Resets the encoder
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::Reset(TRequestStatus &aStatus)
+{
+
+    PRINT((_L("CVideoEncoder::Reset() in")));    
+
+    iPreviousTimeStamp = TTimeIntervalMicroSeconds(0);
+
+    iResetRequestStatus = &aStatus;
+
+    if ( iFatalError )
+        {
+        MtroAsyncStopComplete();
+        }
+    else
+        {
+        TRAPD(err, iTranscoder->AsyncStopL());
+        if (err != KErrNone)
+            iMonitor->Error(err);
+        }
+
+	iStarted = EFalse;
+
+    PRINT((_L("CVideoEncoder::Reset() out")));
+}
+
+void CVideoEncoder::Reset()
+{
+
+    PRINT((_L("CVideoEncoder::Reset() (sync.) in")));
+
+    iPreviousTimeStamp = TTimeIntervalMicroSeconds(0);
+
+    if ( !iFatalError )
+    {
+        if (iStarted) 
+        {            
+            TRAPD(err, iTranscoder->StopL());
+            if (err != KErrNone)
+                iMonitor->Error(err);
+        }
+    }
+
+	iStarted = EFalse;
+
+    PRINT((_L("CVideoEncoder::Reset() (sync.) out")));
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::RunL
+// Active object running method.
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::RunL()
+{
+
+    // Timer elapsed, complete encoding request
+    // with KErrCancel
+
+    PRINT((_L("CVideoEncoder::RunL() in")));
+
+    if (iTimerRequestPending)
+    {
+        iTimerRequestPending = EFalse;
+        if (iEncodeRequestStatus)
+        {
+#ifdef _DEBUG
+            TTime current;
+            current.UniversalTime();
+            TInt64 time = current.MicroSecondsFrom(iEncodeStartTime).Int64();    
+            PRINT((_L("CVideoEncoder::RunL(), completing request, time since encoding started %d"), I64INT( time )));
+#endif
+
+            VEASSERT(*iEncodeRequestStatus == KRequestPending);
+            // complete request
+            User::RequestComplete(iEncodeRequestStatus, KErrCancel);
+            iEncodeRequestStatus = 0;
+			iEncodePending = EFalse;
+        }
+    }
+    PRINT((_L("CVideoEncoder::RunL() out")));
+
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::RunError
+// Active object error method.
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVideoEncoder::RunError(TInt aError)
+{
+    PRINT((_L("CVideoEncoder::RunError() in")));
+
+    Cancel();
+        
+    iMonitor->Error(aError);
+
+    PRINT((_L("CVideoEncoder::RunError() out")));
+    
+    return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CVideoEncoder::DoCancel
+// Active object cancelling method
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::DoCancel()
+{
+
+    PRINT((_L("CVideoEncoder::DoCancel() in")));
+
+    // Cancel our timer request if we have one
+    if ( iTimerRequestPending )
+    {
+        iTimer.Cancel();
+        iTimerRequestPending = EFalse;
+        return;
+    }
+
+}
+       
+// ---------------------------------------------------------
+// CVideoEncoder::EncodeFrameL
+// Encodes a frame
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::EncodeFrameL(TPtr8& aYUVFrame, TRequestStatus &aStatus, TTimeIntervalMicroSeconds aTimeStamp)
+    {
+    PRINT((_L("CVideoEncoder::EncodeFrameL() in, aTimeStamp = %d"), I64INT( aTimeStamp.Int64() ) ));
+
+    if ( iFatalError )
+        {
+        PRINT((_L("CVideoEncoder::EncodeFrameL() can't encode since fatal error has occurred earlier")));
+        User::Leave( KErrGeneral );
+        }
+
+    iEncodeRequestStatus = &aStatus;
+
+	if (!iStarted)
+	{
+		PRINT((_L("CVideoEncoder::EncodeFrameL() - starting devVideoRec")));
+		//iTranscoder->StopL();  // NOTE: needed ??
+		iTranscoder->StartL();
+		iStarted = ETrue;
+	}	 
+
+    // wrap input frame to encoder input buffer
+    iInputBuffer.Set(aYUVFrame);
+    iInputPicture->iRawData = &iInputBuffer;   
+    iInputPicture->iDataSize.SetSize(iFrameSize.iWidth, iFrameSize.iHeight);
+
+    if (aTimeStamp > TTimeIntervalMicroSeconds(0))
+    {
+        TInt64 diff = aTimeStamp.Int64() - iPreviousTimeStamp.Int64();        
+
+        if (diff < 0)
+        {
+            aTimeStamp = iPreviousTimeStamp.Int64() + TInt64(66667);
+        }
+        // NOTE: Could the real difference between two consecutive
+        //       frames be used instead of assuming 15 fps ?
+    }
+    iPreviousTimeStamp = aTimeStamp;
+
+    iInputPicture->iTimestamp = aTimeStamp;
+    //iInputPicture->iLink = NULL;
+    iInputPicture->iUser = this;
+
+#ifdef _DEBUG
+    iEncodeStartTime.UniversalTime();
+#endif
+
+
+	iEncodePending = ETrue;
+
+    iTranscoder->SendPictureToTranscoderL( iInputPicture );
+
+    PRINT((_L("CVideoEncoder::EncodeFrameL() out")));
+
+    }
+
+
+// ---------------------------------------------------------
+// CVideoEncoder::GetBuffer
+// Gets encoded frame bitstream buffer
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TPtrC8& CVideoEncoder::GetBufferL(TBool& aKeyFrame)
+    {
+    if ( iFatalError )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    VEASSERT(iDataBuffer->Length() > 0);
+
+    PRINT((_L("CVideoEncoder::GetBufferL(), keyFrame = %d"), iKeyFrame));    
+
+    aKeyFrame = iKeyFrame;    
+        
+    iReturnDes.Set(iDataBuffer->Des()); 
+    return iReturnDes;    
+ 
+    }
+
+// ---------------------------------------------------------
+// CVideoEncoder::ReturnBuffer
+// Returns used bitstream buffer to devVideoRec
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::ReturnBuffer()
+    {
+    if ( iFatalError )
+        {
+        return;
+        }
+        
+    iDataBuffer->Des().Zero();
+
+    }
+
+// ---------------------------------------------------------
+// CVideoEncoder::SetupEncoderL
+// Private helper method to select & setup the encoder 
+// plugin devvr must use
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVideoEncoder::SetupEncoderL()
+    {
+
+    if ( !(iTranscoder->SupportsOutputVideoFormat(iMimeType) ) )
+        {
+        User::Leave(KErrNotSupported);
+        }             
+        
+    TTRVideoFormat videoInputFormat;
+    TTRVideoFormat videoOutputFormat;
+    
+    videoInputFormat.iSize = iFrameSize;
+    videoInputFormat.iDataType = CTRTranscoder::ETRYuvRawData420;
+
+    videoOutputFormat.iSize = iFrameSize;
+    videoOutputFormat.iDataType = CTRTranscoder::ETRDuCodedPicture;
+        
+    iTranscoder->OpenL( this,
+                        CTRTranscoder::EEncoding,
+                        KNullDesC8,
+                        iMimeType,
+                        videoInputFormat,
+                        videoOutputFormat,
+                        EFalse );
+
+    // default, will be updated by ParseVolHeader
+    iTimeIncrementResolution = KTimeIncrementResolutionHW;    //KTimeIncrementResolutionSW;
+    
+    iTranscoder->SetVideoBitRateL(iBitRate);
+    
+    iTranscoder->SetFrameRateL(iFrameRate);    
+           
+    iTranscoder->SetChannelBitErrorRateL(0.0);
+       
+    // Get processing time estimate from transcoder, divide it by the framerate to get processing time per frame
+    // and then multiply it by 2 to get some safety margin and by unit conversion factor 1000000. 
+    // The delay is used to determine if a frame was skipped, hence there should be some margin.
+#ifdef __WINSCW__
+    iMaxEncodingDelay = 5000000;    // emulator can be really slow, use 5 seconds timeout
+#else    
+    iMaxEncodingDelay = (TUint)(2*1000000*iTranscoder->EstimateTranscodeTimeFactorL(videoInputFormat,videoOutputFormat)/iFrameRate);
+    iMaxEncodingDelay += 100000;  // Add 100 ms for safety margin
+#endif
+    
+    TTRVideoCodingOptions codingOptions;
+    codingOptions.iSyncIntervalInPicture = 0;
+    codingOptions.iMinRandomAccessPeriodInSeconds = (TInt) (1.0 / iRandomAccessRate);
+    
+    // NOTE: What about these ???
+    codingOptions.iDataPartitioning = EFalse;
+    codingOptions.iReversibleVLC = EFalse;
+    codingOptions.iHeaderExtension = 0;
+   
+    iTranscoder->SetVideoCodingOptionsL(codingOptions);
+   
+    iTranscoder->SetVideoPictureSinkOptionsL(iFrameSize, this);
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::MtroSetInputFrameRate
+// Sets input sequence frame rate for encoding
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::MtroSetInputFrameRate(TReal& aRate)
+    {
+     
+    aRate = iInputFrameRate;
+        
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::MtroPictureFromTranscoder
+// Called by transcoder to return the input picture buffer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::MtroPictureFromTranscoder(TTRVideoPicture* aPicture)
+    {
+    PRINT((_L("CVideoEncoder::MtroPictureFromTranscoder() %x"), aPicture));
+    
+    if (iInputPicture != aPicture)
+    {
+        iMonitor->Error(KErrGeneral);
+        return;
+    }
+        
+    if (iEncodePending)
+        {                
+        if (!iTimerRequestPending)
+            {
+            // Activate timer to wait for encoding, if the encoding didn't complete already. 
+            // Timeout is needed since we don't get notification if frame was skipped.
+            SetActive();
+            iStatus = KRequestPending;        
+            iTimer.After(iStatus, TTimeIntervalMicroSeconds32(iMaxEncodingDelay));
+            iTimerRequestPending = ETrue;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::WriteBufferL
+// Called by transcoder to notify that new bitsream buffer is ready
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::WriteBufferL(CCMRMediaBuffer* aBuffer)
+    {
+    
+    PRINT((_L("CVideoEncoder::WriteBufferL(), iEncodePending = %d"), iEncodePending));
+    
+#ifdef _DEBUG
+    TTime current;
+    current.UniversalTime();
+    TInt64 time = current.MicroSecondsFrom(iEncodeStartTime).Int64();
+	PRINT((_L("CVideoEncoder::WriteBufferL(), time spent encoding = %d ms, iEncodeRequestStatus = 0x%x"), 
+		(I64INT(time))/1000 ,iEncodeRequestStatus));
+
+#endif
+
+    if (aBuffer->Type() == CCMRMediaBuffer::EVideoMPEG4DecSpecInfo)
+	{
+		// copy data to bitstream buffer
+	    TPtr8 ptr = iDataBuffer->Des();		    
+	    ptr.Copy( aBuffer->Data() );	    
+	    return;		
+	}
+
+    // Cancel timer
+    Cancel();
+
+	iEncodePending = EFalse;	
+	
+	if (aBuffer->BufferSize() == 0)
+	{
+	    PRINT((_L("CVideoEncoder::WriteBufferL() buffer length == 0")));
+	    
+    	if ( iEncodeRequestStatus != 0 )
+        {
+    		// complete request
+    		User::RequestComplete(iEncodeRequestStatus, KErrUnderflow);
+    		iEncodeRequestStatus = 0;
+    	}	    
+	    return;
+	}
+		
+	VEASSERT(aBuffer->Data().Length() <= KMaxCodedPictureSizeVGA);		    
+	
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+    TInt avcFrameLen = 0;
+    if ( iMimeType.FindF(KVedMimeTypeAVC) != KErrNotFound )
+    {           
+       // get avc frame length
+       TUint8* tmp = const_cast<TUint8*>(aBuffer->Data().Ptr() + aBuffer->Data().Length());
+       // support for 1 frame in 1 NAL unit currently
+       tmp -= 4;
+       TInt numNalUnits = TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
+       if (numNalUnits > 0) { }
+       
+       VEASSERT( numNalUnits == 1 );       
+       tmp -=4;
+              
+       avcFrameLen = tmp[0] + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);                     
+       
+       TInt error = KErrNone;
+       // check that there is enough room for length field and the frame
+       if ( iDataBuffer->Des().MaxLength() < (avcFrameLen + 4) )
+           TRAP( error, iDataBuffer->ReAllocL(avcFrameLen + 4) );
+           
+       if (error != KErrNone)
+       {
+           iMonitor->Error(error);
+           return;
+       }
+       
+       TUint8* buf = const_cast<TUint8*>(iDataBuffer->Des().Ptr());
+       
+       // set length
+       buf[0] = TUint8((avcFrameLen >> 24) & 0xff);
+       buf[1] = TUint8((avcFrameLen >> 16) & 0xff);
+       buf[2] = TUint8((avcFrameLen >> 8) & 0xff);
+       buf[3] = TUint8(avcFrameLen & 0xff);
+       
+       iDataBuffer->Des().SetLength(4);
+    }
+#endif        
+			
+	// copy data to bitstream buffer
+	TPtr8 ptr = iDataBuffer->Des();
+	
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+	if ( iMimeType.FindF(KVedMimeTypeAVC) != KErrNotFound )
+	{
+	    ptr.Append( aBuffer->Data().Ptr(), avcFrameLen );
+	}
+	else
+#endif
+    {
+        ptr.Append( aBuffer->Data() );
+    }
+	
+	// save keyframe flag
+	iKeyFrame = aBuffer->RandomAccessPoint();
+			
+	if ( iEncodeRequestStatus != 0 )
+    {
+		// complete request
+		User::RequestComplete(iEncodeRequestStatus, KErrNone);
+		iEncodeRequestStatus = 0;
+	}
+
+    // --> user calls GetBuffer();	    
+    
+    }
+    
+TInt CVideoEncoder::SetVideoFrameSize(TSize /*aSize*/)
+    {
+    return KErrNone;    
+    }
+    
+TInt CVideoEncoder::SetAverageVideoBitRate(TInt /*aSize*/)
+    {
+    return KErrNone;    
+    }
+    
+TInt CVideoEncoder::SetMaxVideoBitRate(TInt /*aSize*/)
+    {
+    return KErrNone;    
+    }
+    
+TInt CVideoEncoder::SetAverageAudioBitRate(TInt /*aSize*/)
+    {
+    return KErrNone;    
+    }
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::MtroFatalError
+// Called by transcoder when a fatal error has occurred
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::MtroFatalError(TInt aError)
+    {
+
+    PRINT((_L("CVideoEncoder::MtroFatalError() %d"), aError));
+    iFatalError = ETrue;
+
+    iMonitor->Error(aError);
+    
+    }
+    
+void CVideoEncoder::MtroReturnCodedBuffer(CCMRMediaBuffer* /*aBuffer*/)
+    {
+        
+        User::Panic(_L("CVIDEOENCODER"), EInternalAssertionFailure);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::MdvroInitializeComplete
+// Called by transcoder when initialization is complete
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::MtroInitializeComplete(TInt aError)
+    {
+    PRINT((_L("CVideoEncoder::MtroInitializeComplete %d, iResetRequestStatus %x"), aError, iResetRequestStatus));
+
+    VEASSERT(iResetRequestStatus);
+
+    if ( aError != KErrNone )    
+    {        
+        iMonitor->Error(aError);
+        if ( iResetRequestStatus != 0 )
+        {            
+            User::RequestComplete(iResetRequestStatus, aError);
+            iResetRequestStatus = 0;
+        }
+        return;
+    }
+    
+    TInt error = KErrNone;    
+    // Handle MPEG-4 VOL / AVC SPS/PPS data reading/writing            
+    TRAP(error, HandleCodingStandardSpecificInfoL());
+    
+    if ( error != KErrNone )
+        iMonitor->Error(error); 
+
+	if ( iResetRequestStatus != 0 )
+    {		
+		PRINT((_L("CVideoEncoder::MtroInitializeComplete() complete request")));
+		// complete request:
+        User::RequestComplete(iResetRequestStatus, error);
+		iResetRequestStatus = 0;
+	}
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::MtroAsyncStopComplete
+// Called by transcoder when all pictures have been processed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::MtroAsyncStopComplete()
+    {
+    
+    PRINT((_L("CVideoEncoder::MtroAsyncStopComplete()")));
+    
+    if ( iResetRequestStatus != 0 )
+    {
+		PRINT((_L("CVideoEncoder::MdvroStreamEnd() complete request")));
+        // complete request
+        User::RequestComplete(iResetRequestStatus, KErrNone);
+        iResetRequestStatus = 0;
+    }
+       
+    }
+
+// -----------------------------------------------------------------------------
+// CVideoEncoder::GetTimeIncrementResolution
+// Gets time increment resolution used in MPEG-4 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CVideoEncoder::GetTimeIncrementResolution() const
+    {
+    if ( iVolReader->TimeIncrementResolution() != 0 )
+        return iVolReader->TimeIncrementResolution();
+    
+    return iTimeIncrementResolution;
+    }
+    
+// -----------------------------------------------------------------------------
+// CVideoEncoder::HandleCodingStandardSpecificInfoL
+// Parses the MPEG-4 VOL header / AVC Dec. configuration record
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CVideoEncoder::HandleCodingStandardSpecificInfoL()
+    {
+
+    // Parse the VOL header for mpeg-4
+    if ( iMimeType.FindF(KVedMimeTypeMPEG4Visual) != KErrNotFound )
+        {
+        HBufC8* headerData = iTranscoder->GetCodingStandardSpecificInitOutputLC();
+        if ( headerData != 0 )
+            {
+            iVolReader->ParseVolHeaderL( (TDesC8&) *headerData );
+            
+            // Insert VOL header to bitstream buffer
+	        TPtr8 ptr = iDataBuffer->Des();		
+	        ptr.Append( *headerData );
+            
+            CleanupStack::PopAndDestroy( headerData );
+            }
+        }
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING         
+    // Parse & write SPS/PPS data for AVC
+    else if ( iMimeType.FindF(KVedMimeTypeAVC) != KErrNotFound )
+        {
+        HBufC8* headerData = iTranscoder->GetCodingStandardSpecificInitOutputLC();
+        
+        if ( headerData != 0 )
+            {   
+            
+            HBufC8* outputAVCHeader = 0;
+            // is the max. size of AVCDecoderConfigurationRecord known here ??
+            outputAVCHeader = (HBufC8*) HBufC8::NewLC(16384);            
+            TPtr8 ptr = outputAVCHeader->Des();
+	            
+	        // parse header & convert it to AVCDecoderConfigurationRecord -format
+	        iAvcEdit->ConvertAVCHeaderL(*headerData, ptr);	            
+	        
+	        // save it to avc module for later use
+	        iAvcEdit->SaveAVCDecoderConfigurationRecordL(ptr, ETrue /* aFromEncoder */); 
+
+            CleanupStack::PopAndDestroy( 2 );  // headerData, outputAVCHeader
+            
+            }
+        }
+#endif
+        
+    }