--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/vedtranscoder/src/Ctrtranscoderimp.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,4118 @@
+/*
+* 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:
+* Transcoder Implementation.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <centralrepository.h>
+#include "ctrvideopicturesink.h"
+#include "ctrtranscoderobserver.h"
+#include "ctrtranscoderimp.h"
+#include "ctrsettings.h"
+#include "ctrhwsettings.h"
+#include "ctrvideodecoderclient.h"
+#include "ctrvideoencoderclient.h"
+#include "ctrscaler.h"
+#include "ctrprivatecrkeys.h"
+
+
+// MACROS
+#define TRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CTRANSCODERIMP"), KErrAbort))
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CTRTranscoderImp* CTRTranscoderImp::NewL(MTRTranscoderObserver& aObserver)
+ {
+ PRINT(_L("CTRTranscoderImp::NewL(), In"))
+
+ CTRTranscoderImp* self = new (ELeave) CTRTranscoderImp(aObserver);
+ CleanupStack::PushL( reinterpret_cast<CTRTranscoder*>(self) );
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ PRINT(_L("CTRTranscoderImp::NewL(), Out"))
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::CTRTranscoderImp
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CTRTranscoderImp::CTRTranscoderImp(MTRTranscoderObserver& aObserver) :
+ CActive(EPriorityStandard),
+ iObserver(aObserver)
+ {
+ CActiveScheduler::Add(this);
+ iVideoDecoderClient = NULL;
+ iVideoEncoderClient = NULL;
+ iRealTime = EFalse;
+ iMediaSink = NULL;
+ iScaler = NULL;
+ iPictureSink = NULL;
+ iPictureSinkTemp = NULL;
+ iState = ETRNone;
+ iEncoderInitStatus = KTRErrNotReady; /*Internal error status*/
+ iDecoderInitStatus = KTRErrNotReady;
+ iEncoderStreamEnd = EFalse;
+ iDecoderStreamEnd = EFalse;
+ iDataArray = NULL;
+ iVideoPictureArray = NULL;
+ iDecodedPicture = NULL;
+ iBitRateSetting = EFalse;
+ iFatalError = KErrNone;
+ iOptimizedDataTransfer = EFalse;
+ iEncoderEnabled = ETrue;
+ iPictureSinkEnabled = EFalse;
+ iPictureSinkClientSetting = EFalse;
+ iSetRandomAccessPoint = EFalse;
+ iEncoderEnabledSettingChanged = EFalse;
+ iPictureSinkSettingChanged = EFalse;
+ iEncoderEnableClientSetting = ETrue;
+ iWaitPictureFromClient = NULL;
+ iWaitNewDecodedPicture = NULL;
+ iNewEvent = NULL;
+ iCurrentPictureSinkEnabled = EFalse;
+ iCurrentAsyncPictureSinkEnabled = EFalse;
+ iCurrentEncoderEnabled = ETrue;
+ iCurrentAsyncEncoderEnabled = ETrue;
+ iCurrentRandomAccess = EFalse;
+ iAsyncStop = EFalse;
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingDefault;
+
+
+ // Set offset for queues
+ iTranscoderPictureQueue.SetOffset( static_cast<TInt>( _FOFF( TVideoPicture, iLink )));
+ iEncoderPictureQueue.SetOffset( static_cast<TInt>( _FOFF( TVideoPicture, iLink )));
+ iCIPictureBuffersQueue.SetOffset( static_cast<TInt>( _FOFF( TVideoPicture, iLink )));
+ iTranscoderTRPictureQueue.SetOffset( static_cast<TInt>( _FOFF( TTRVideoPicture, iLink )));
+ iContainerWaitQueue.SetOffset( static_cast<TInt>( _FOFF( TVideoPicture, iLink )));
+ iTranscoderEventSrc.SetOffset( static_cast<TInt>( _FOFF( CTREventItem, iLink )));
+ iTranscoderEventQueue.SetOffset( static_cast<TInt>( _FOFF( CTREventItem, iLink )));
+ iTranscoderAsyncEventQueue.SetOffset( static_cast<TInt>( _FOFF( CTREventItem, iLink )));
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::ConstructL()
+ {
+ PRINT((_L("CTRTranscoderImp::ConstructL(), In")))
+
+ // Allocate ivent quque
+ iEvents = NULL;
+ iEvents = new (ELeave) CTREventItem[KNumberOfEvents];
+
+ // Fill event's queue
+ for (TInt i = 0; i < KNumberOfEvents; i ++)
+ {
+ iEvents[i].Reset();
+ iTranscoderEventSrc.AddLast( iEvents[i] );
+ }
+
+ LoadCodecUids();
+
+ PRINT((_L("CTRTranscoderImp::ConstructL(), Out")))
+ }
+
+
+// ---------------------------------------------------------
+// CTRTranscoderImp::~CTRTranscoderImp()
+// Destructor
+// ---------------------------------------------------------
+//
+CTRTranscoderImp::~CTRTranscoderImp()
+ {
+ PRINT((_L("CTRTranscoderImp::~CTRTranscoderImp(), In")))
+ TInt i = 0;
+
+
+ if ( iState == ETRRunning )
+ {
+ TRAPD(status, this->StopL());
+ PRINT((_L("CTRTranscoderImp::~CTRTranscoderImp(), StopL status[%d]"), status))
+
+ if (status != KErrNone)
+ {
+ // Nothing to do, since destruction of the app
+ }
+ }
+
+ Cancel();
+
+ if (iVideoDecoderClient)
+ {
+ delete iVideoDecoderClient;
+ iVideoDecoderClient = NULL;
+ }
+
+ if (iVideoEncoderClient)
+ {
+ delete iVideoEncoderClient;
+ iVideoEncoderClient = NULL;
+ }
+
+ if (iScaler)
+ {
+ delete iScaler;
+ iScaler = NULL;
+ }
+
+ if (iDataArray)
+ {
+ for (i = 0; i < KTRPictureBuffersNumber; i ++)
+ {
+ if ( iDataArray[i] )
+ {
+ delete[] iDataArray[i];
+ iDataArray[i] = NULL;
+ }
+ }
+
+ delete[] iDataArray;
+ iDataArray = NULL;
+ }
+
+ if ( (iMode == EEncoding) && (iInputPictureSize == iOutputPictureSize) )
+ {
+ // Clean iRawData ptrs, since the actual memory was allocated by the client
+ if (iVideoPictureArray)
+ {
+ for (i = 0; i < KTRPictureBuffersNumber; i ++)
+ {
+ if (iVideoPictureArray[i].iData.iRawData)
+ {
+ iVideoPictureArray[i].iData.iRawData = NULL;
+ }
+ }
+ }
+ }
+
+ if (iVideoPictureArray)
+ {
+ for (i = 0; i < KTRPictureBuffersNumber; i ++)
+ {
+ if (iVideoPictureArray[i].iData.iRawData)
+ {
+ delete iVideoPictureArray[i].iData.iRawData;
+ iVideoPictureArray[i].iData.iRawData = NULL;
+ }
+ }
+
+ delete[] iVideoPictureArray;
+ iVideoPictureArray = NULL;
+ }
+
+ if (iTRVideoPictureArray)
+ {
+ delete[] iTRVideoPictureArray;
+ iTRVideoPictureArray = NULL;
+ }
+
+ if (iEvents)
+ {
+ delete[] iEvents;
+ }
+
+ PRINT((_L("CTRTranscoderImp::~CTRTranscoderImp(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SupportsInputVideoFormat
+// Checks whether given input format is supported
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CTRTranscoderImp::SupportsInputVideoFormat(const TDesC8& aMimeType)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), In")))
+ TBool supports = EFalse;
+
+
+ if ( aMimeType == KNullDesC8 )
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), Mime type is undefined")))
+ return EFalse;
+ }
+
+ // Check video decoder
+ if (!iVideoDecoderClient)
+ {
+ // Parse MIME
+ TRAPD(status, this->ParseMimeTypeL(aMimeType, ETrue));
+
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), ParseMimeTypeL[%d]"), status))
+ return EFalse;
+ }
+
+ // Create the decoder client first
+ TRAP( status, iVideoDecoderClient = CTRVideoDecoderClient::NewL(*this) );
+
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), VideoDecClient status[%d]"), status))
+ iVideoDecoderClient = NULL;
+ return EFalse;
+ }
+ }
+
+ // Choose the correct codec Uids to use
+ TInt preferredUid = 0;
+ TInt fallbackUid = 0;
+ TInt resolutionUid = 0;
+
+ if (iInputCodec == EH263)
+ {
+ preferredUid = iH263DecoderUid;
+ fallbackUid = KTRFallbackDecoderUidH263;
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() H.263, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() H.263, fallback = 0x%x"), fallbackUid))
+
+ if (iInputPictureSize.iWidth <= iH263DecoderLowResThreshold)
+ {
+ resolutionUid = iH263DecoderLowResUid;
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() H.263, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+ else if (iInputCodec == EH264)
+ {
+ preferredUid = iH264DecoderUid;
+ fallbackUid = KTRFallbackDecoderUidH264;
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() AVC, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() AVC, fallback = 0x%x"), fallbackUid))
+
+ if (iInputPictureSize.iWidth <= iH264DecoderLowResThreshold)
+ {
+ resolutionUid = iH264DecoderLowResUid;
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() AVC, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+ else
+ {
+ preferredUid = iMPEG4DecoderUid;
+ fallbackUid = KTRFallbackDecoderUidMPEG4;
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() MPEG-4, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() MPEG-4, fallback = 0x%x"), fallbackUid))
+
+ if (iInputPictureSize.iWidth <= iMPEG4DecoderLowResThreshold)
+ {
+ resolutionUid = iMPEG4DecoderLowResUid;
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() MPEG-4, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+
+ if (resolutionUid != 0)
+ {
+ preferredUid = resolutionUid;
+ }
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat() preferred = 0x%x"), preferredUid))
+
+ supports = iVideoDecoderClient->SupportsCodec(iInputMimeType, iInputShortMimeType, preferredUid, fallbackUid);
+
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), supports[%d] Out"), supports))
+ return supports;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SupportsOutputVideoFormat
+// Checks whether given output format is supported
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CTRTranscoderImp::SupportsOutputVideoFormat(const TDesC8& aMimeType)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat(), In")))
+ TBool supports = EFalse;
+
+
+ if ( aMimeType == KNullDesC8 )
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat(), Mime type is undefined")))
+ return EFalse;
+ }
+
+ // Check video encoder
+ if (!iVideoEncoderClient)
+ {
+ // Parse MIME
+ TRAPD(status, this->ParseMimeTypeL(aMimeType, EFalse));
+
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsInputVideoFormat(), ParseMimeTypeL[%d]"), status))
+ return EFalse;
+ }
+
+ // Create the encoder client first
+ TRAP(status, iVideoEncoderClient = CTRVideoEncoderClient::NewL(*this) );
+
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat(), VideoEncClient status[%d]"), status))
+ iVideoEncoderClient = NULL;
+ return EFalse;
+ }
+ }
+
+ // Choose the correct codec Uids to use
+ TInt preferredUid = 0;
+ TInt fallbackUid = 0;
+ TInt resolutionUid = 0;
+
+ if (iOutputCodec == EH263)
+ {
+ preferredUid = iH263EncoderUid;
+ fallbackUid = KTRFallbackEncoderUidH263;
+
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() H.263, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() H.263, fallback = 0x%x"), fallbackUid))
+
+ if (iOutputPictureSize.iWidth <= iH263EncoderLowResThreshold)
+ {
+ resolutionUid = iH263EncoderLowResUid;
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() H.263, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+ else if (iOutputCodec == EH264)
+ {
+ preferredUid = iH264EncoderUid;
+ fallbackUid = KTRFallbackEncoderUidH264;
+
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() AVC, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() AVC, fallback = 0x%x"), fallbackUid))
+
+ if (iOutputPictureSize.iWidth <= iH264EncoderLowResThreshold)
+ {
+ resolutionUid = iH264EncoderLowResUid;
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() AVC, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+ else
+ {
+ preferredUid = iMPEG4EncoderUid;
+ fallbackUid = KTRFallbackEncoderUidMPEG4;
+
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() MPEG-4, preferred = 0x%x"), preferredUid))
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() MPEG-4, fallback = 0x%x"), fallbackUid))
+
+ if (iOutputPictureSize.iWidth <= iMPEG4EncoderLowResThreshold)
+ {
+ resolutionUid = iMPEG4EncoderLowResUid;
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() MPEG-4, below, resolutions = 0x%x"), resolutionUid))
+ }
+ }
+
+ if (resolutionUid != 0)
+ {
+ preferredUid = resolutionUid;
+ }
+
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat() preferred = 0x%x"), preferredUid))
+
+ supports = iVideoEncoderClient->SupportsCodec(iOutputMimeType, iOutputShortMimeType, preferredUid, fallbackUid);
+
+ PRINT((_L("CTRTranscoderImp::SupportsOutputVideoFormat(), supports[%d] Out"), supports))
+ return supports;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::LoadCodecUids
+// Loads codec Uids from central repository
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::LoadCodecUids()
+ {
+ PRINT((_L("CTRTranscoderImp::LoadCodecUids(), In")))
+
+ CRepository* repository = NULL;
+
+ TRAPD(error, repository = CRepository::NewL(KCRUidTranscoder));
+
+ if (error != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::LoadCodecUids(), Error: %d, Out"), error))
+ return;
+ }
+
+ if (repository->Get(KTRH263DecoderUid, iH263DecoderUid) != KErrNone)
+ {
+ iH263DecoderUid = 0;
+ }
+ if (repository->Get(KTRH264DecoderUid, iH264DecoderUid) != KErrNone)
+ {
+ iH264DecoderUid = 0;
+ }
+ if (repository->Get(KTRMPEG4DecoderUid, iMPEG4DecoderUid) != KErrNone)
+ {
+ iMPEG4DecoderUid = 0;
+ }
+
+ if (repository->Get(KTRH263EncoderUid, iH263EncoderUid) != KErrNone)
+ {
+ iH263EncoderUid = 0;
+ }
+ if (repository->Get(KTRH264EncoderUid, iH264EncoderUid) != KErrNone)
+ {
+ iH264EncoderUid = 0;
+ }
+ if (repository->Get(KTRMPEG4EncoderUid, iMPEG4EncoderUid) != KErrNone)
+ {
+ iMPEG4EncoderUid = 0;
+ }
+
+ if (repository->Get(KTRH263DecoderLowResUid, iH263DecoderLowResUid) != KErrNone)
+ {
+ iH263DecoderLowResUid = 0;
+ }
+ if (repository->Get(KTRH264DecoderLowResUid, iH264DecoderLowResUid) != KErrNone)
+ {
+ iH264DecoderLowResUid = 0;
+ }
+ if (repository->Get(KTRMPEG4DecoderLowResUid, iMPEG4DecoderLowResUid) != KErrNone)
+ {
+ iMPEG4DecoderLowResUid = 0;
+ }
+
+ if (repository->Get(KTRH263EncoderLowResUid, iH263EncoderLowResUid) != KErrNone)
+ {
+ iH263EncoderLowResUid = 0;
+ }
+ if (repository->Get(KTRH264EncoderLowResUid, iH264EncoderLowResUid) != KErrNone)
+ {
+ iH264EncoderLowResUid = 0;
+ }
+ if (repository->Get(KTRMPEG4EncoderLowResUid, iMPEG4EncoderLowResUid) != KErrNone)
+ {
+ iMPEG4EncoderLowResUid = 0;
+ }
+
+ if (repository->Get(KTRH263DecoderLowResThreshold, iH263DecoderLowResThreshold) != KErrNone)
+ {
+ iH263DecoderLowResThreshold = 0;
+ }
+ if (repository->Get(KTRH264DecoderLowResThreshold, iH264DecoderLowResThreshold) != KErrNone)
+ {
+ iH264DecoderLowResThreshold = 0;
+ }
+ if (repository->Get(KTRMPEG4DecoderLowResThreshold, iMPEG4DecoderLowResThreshold) != KErrNone)
+ {
+ iMPEG4DecoderLowResThreshold = 0;
+ }
+
+ if (repository->Get(KTRH263EncoderLowResThreshold, iH263EncoderLowResThreshold) != KErrNone)
+ {
+ iH263EncoderLowResThreshold = 0;
+ }
+ if (repository->Get(KTRH264EncoderLowResThreshold, iH264EncoderLowResThreshold) != KErrNone)
+ {
+ iH264EncoderLowResThreshold = 0;
+ }
+ if (repository->Get(KTRMPEG4EncoderLowResThreshold, iMPEG4EncoderLowResThreshold) != KErrNone)
+ {
+ iMPEG4EncoderLowResThreshold = 0;
+ }
+
+ delete repository;
+
+ PRINT((_L("CTRTranscoderImp::LoadCodecUids(), Out")))
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::OpenL
+// Opens the transcoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::OpenL( MCMRMediaSink* aMediaSink,
+ CTRTranscoder::TTROperationalMode aMode,
+ const TDesC8& aInputMimeType,
+ const TDesC8& aOutputMimeType,
+ const TTRVideoFormat& aVideoInputFormat,
+ const TTRVideoFormat& aVideoOutputFormat,
+ TBool aRealTime )
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), In, OperationalMode[%d]"), aMode))
+ TBool supports = EFalse;
+
+ if (iState != ETRNone)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ // Set picture size
+
+ // If decoding then accept all resolutions that are divisible by 16
+ if ( (aMode == EDecoding) &&
+ ((aVideoInputFormat.iSize.iWidth & 0xf) == 0) &&
+ ((aVideoInputFormat.iSize.iHeight & 0xf) == 0) &&
+ ((aVideoOutputFormat.iSize.iWidth & 0xf) == 0) &&
+ ((aVideoOutputFormat.iSize.iHeight & 0xf) == 0) )
+ {
+ iOutputPictureSize = aVideoOutputFormat.iSize;
+ iInputPictureSize = aVideoInputFormat.iSize;
+ }
+ else if ( ( this->IsValid( const_cast<TSize&>(aVideoOutputFormat.iSize) ) ) &&
+ ( this->IsValid( const_cast<TSize&>(aVideoInputFormat.iSize) ) ) )
+ {
+ iOutputPictureSize = aVideoOutputFormat.iSize;
+ iInputPictureSize = aVideoInputFormat.iSize;
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), picture size is not valid")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // By default the decoded picture is the same size as the input picture
+ iDecodedPictureSize = iInputPictureSize;
+
+ // Create Scaler
+ if (!iScaler)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), create scaler")))
+ iScaler = CTRScaler::NewL();
+ }
+
+
+ switch(aMode)
+ {
+ case EFullTranscoding:
+ {
+ if ( (aInputMimeType != KNullDesC8) && (aOutputMimeType != KNullDesC8) && (aMediaSink != NULL) )
+ {
+ if ( (aVideoInputFormat.iDataType != CTRTranscoder::ETRDuCodedPicture) &&
+ (aVideoInputFormat.iDataType != CTRTranscoder::ETRDuVideoSegment) ||
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRDuCodedPicture) &&
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRDuVideoSegment) )
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), data format is not supported in selected operational mode")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // Parse mime type and check / define max parameters for requested codec profile-level.
+ this->ParseMimeTypeL(aInputMimeType, ETrue);
+ this->ParseMimeTypeL(aOutputMimeType, EFalse);
+
+ if (!iVideoDecoderClient)
+ {
+ iVideoDecoderClient = CTRVideoDecoderClient::NewL(*this);
+ }
+
+ // Check input format
+ supports = this->SupportsInputVideoFormat( iInputShortMimeType.Des() );
+
+ if (!supports)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), Input format is not supported by video decoder")))
+ User::Leave(KErrNotSupported);
+ }
+
+ if (!iVideoEncoderClient)
+ {
+ iVideoEncoderClient = CTRVideoEncoderClient::NewL(*this);
+ }
+
+ // Check output format
+ supports = this->SupportsOutputVideoFormat( iOutputShortMimeType.Des() );
+
+ if (!supports)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), Output format is not supported by video encoder")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // Inform user about wrong argument
+ User::Leave(KErrArgument);
+ }
+
+ // Set codec parameters
+ iVideoDecoderClient->SetCodecParametersL(iInputCodec, iInputCodecLevel, aVideoInputFormat, aVideoOutputFormat);
+ iVideoEncoderClient->SetCodecParametersL(iOutputCodec, iOutputCodecLevel, aVideoInputFormat, aVideoOutputFormat);
+
+ TBool srcWide = iScaler->IsWideAspectRatio(iInputPictureSize);
+ TBool dstWide = iScaler->IsWideAspectRatio(iOutputPictureSize);
+
+ if (srcWide != dstWide)
+ {
+ // get intermediate size from scaler
+ TSize resolution;
+ TSize bb = TSize(0,0);
+
+ TBool scale = iScaler->GetIntermediateResolution(iInputPictureSize, iOutputPictureSize,
+ resolution, bb);
+
+ if (scale && iVideoDecoderClient->SetDecoderScaling(iInputPictureSize, resolution))
+ {
+
+ PRINT((_L("CTRTranscoderImp::OpenL(), decoder scaling supported")))
+
+ //iDecodedPictureSize = iOutputPictureSize;
+ iDecodedPictureSize = resolution;
+
+ // NOTE: What if decoder init. fails, this would have to be reseted!
+ // Increase the max number of frames in processing since scaling is used
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingScaling;
+ }
+ }
+
+ else if (iVideoDecoderClient->SetDecoderScaling(iInputPictureSize, iOutputPictureSize))
+ {
+ // Scaling is supported
+ iDecodedPictureSize = iOutputPictureSize;
+
+ // Increase the max number of frames in processing since scaling is used
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingScaling;
+ }
+
+ iVideoEncoderClient->SetRealTime(aRealTime);
+
+ break;
+ }
+
+ case EDecoding:
+ {
+ if ( aInputMimeType != KNullDesC8 )
+ {
+ if ( (aVideoInputFormat.iDataType != CTRTranscoder::ETRDuCodedPicture) &&
+ (aVideoInputFormat.iDataType != CTRTranscoder::ETRDuVideoSegment) ||
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRYuvRawData420) &&
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRYuvRawData422) )
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), data format is not supported in selected operational mode")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // Check mime
+ this->ParseMimeTypeL(aInputMimeType, ETrue);
+
+ if (!iVideoDecoderClient)
+ {
+ iVideoDecoderClient = CTRVideoDecoderClient::NewL(*this);
+ }
+
+ // Check input format
+ supports = this->SupportsInputVideoFormat( iInputShortMimeType.Des() );
+
+ if (!supports)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), Input format is not supported by video decoder")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // Inform user about wrong argument
+ User::Leave(KErrArgument);
+ }
+
+ // Set codec information
+ iVideoDecoderClient->SetCodecParametersL(iInputCodec, iInputCodecLevel, aVideoInputFormat, aVideoOutputFormat);
+
+ // Check if decoder supports scaling
+ if (iVideoDecoderClient->SetDecoderScaling(iInputPictureSize, iOutputPictureSize))
+ {
+ // Scaling is supported
+ iDecodedPictureSize = iOutputPictureSize;
+ }
+
+ break;
+ }
+
+ case EEncoding:
+ {
+ if ( aMediaSink && (aOutputMimeType != KNullDesC8) )
+ {
+ if ( (aVideoInputFormat.iDataType != CTRTranscoder::ETRYuvRawData420) &&
+ (aVideoInputFormat.iDataType != CTRTranscoder::ETRYuvRawData422) ||
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRDuCodedPicture) &&
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRDuVideoSegment) )
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), data format is not supported in selected operational mode")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // Check mime
+ this->ParseMimeTypeL(aOutputMimeType, EFalse);
+
+ if (!iVideoEncoderClient)
+ {
+ iVideoEncoderClient = CTRVideoEncoderClient::NewL(*this);
+ }
+
+ // Check output format
+ supports = this->SupportsOutputVideoFormat( iOutputShortMimeType.Des() );
+
+ if (!supports)
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), Output format is not supported by video encoder")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // Inform user about wrong argument
+ User::Leave(KErrArgument);
+ }
+
+ // Set codec parameters
+ iVideoEncoderClient->SetCodecParametersL(iOutputCodec, iOutputCodecLevel, aVideoInputFormat, aVideoOutputFormat);
+
+ break;
+ }
+
+ case EResampling:
+ {
+ if ( (aVideoInputFormat.iDataType != CTRTranscoder::ETRYuvRawData420) ||
+ (aVideoOutputFormat.iDataType != CTRTranscoder::ETRYuvRawData420) )
+ {
+ PRINT((_L("CTRTranscoderImp::OpenL(), data format is not supported in selected operational mode")))
+ User::Leave(KErrNotSupported);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ // Given option is not supported
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ iMode = aMode;
+ iRealTime = aRealTime;
+ iMediaSink = aMediaSink;
+ iState = ETROpened;
+
+ if ( (iMode == EFullTranscoding) || (iMode == EEncoding) )
+ {
+ // Get frame rate for initial input coded stream
+ TReal frameRate = 0.0;
+ iObserver.MtroSetInputFrameRate(frameRate);
+
+ if (frameRate > 0.0)
+ {
+ iVideoEncoderClient->SetInputFrameRate(frameRate);
+ }
+ }
+
+ PRINT((_L("CTRTranscoderImp::OpenL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetVideoBitRateL
+// Sets video bitrate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetVideoBitRateL(TUint aBitRate)
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoBitRateL(), In")))
+
+ if ( (iState != ETROpened) && (iState != ETRInitialized) && (iState != ETRRunning) )
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoBitRateL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ iVideoEncoderClient->SetBitRate(aBitRate);
+ }
+
+ iBitRateSetting = ETrue;
+
+ PRINT((_L("CTRTranscoderImp::SetVideoBitRateL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetFrameRateL
+// Sets frame rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetFrameRateL(TReal aFrameRate)
+ {
+ PRINT((_L("CTRTranscoderImp::SetFrameRateL(), In")))
+
+ if ( (iState != ETROpened) && (iState != ETRInitialized) && (iState != ETRRunning) )
+ {
+ PRINT((_L("CTRTranscoderImp::SetFrameRateL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ iVideoEncoderClient->SetFrameRate(aFrameRate);
+ }
+
+ PRINT((_L("CTRTranscoderImp::SetFrameRateL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetChannelBitErrorRateL
+// Sets channel bit error rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetChannelBitErrorRateL(TReal aErrorRate)
+ {
+ PRINT((_L("CTRTranscoderImp::SetChannelBitErrorRateL(), In")))
+
+ if ( (iState != ETROpened) && (iState != ETRInitialized) && (iState != ETRRunning) )
+ {
+ PRINT((_L("CTRTranscoderImp::SetChannelBitErrorRateL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ iVideoEncoderClient->SetChannelBitErrorRate(aErrorRate);
+ }
+
+ PRINT((_L("CTRTranscoderImp::SetChannelBitErrorRateL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetVideoCodingOptionsL
+// Sets video coding options
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetVideoCodingOptionsL(TTRVideoCodingOptions& aOptions)
+ {
+ if (iState != ETROpened)
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoCodingOptionsL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ iVideoEncoderClient->SetVideoCodingOptionsL(aOptions);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetVideoPictureSinkOptionsL
+// Sets picture sing and options for intermediate format
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetVideoPictureSinkOptionsL(TSize& aSize, MTRVideoPictureSink* aSink)
+ {
+ if (iState == ETRNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoPictureSinkOptionsL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (aSink)
+ {
+ if ((iMode != EDecoding) && (!this->IsValid(aSize)))
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoPictureSinkOptionsL(), invalid size")))
+ User::Leave(KErrNotSupported);
+ }
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ case EDecoding:
+ {
+ if ( aSize == iOutputPictureSize )
+ {
+ iIntermediatePictureSize = aSize;
+ }
+ else
+ {
+ // In full transcoding mode (intermediate picture size = outputTarget size) is supported only
+ PRINT((_L("CTRTranscoderImp::SetVideoPictureSinkOptionsL(), Intermediate picture size is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ break;
+
+ case EEncoding:
+ {
+ if ( (aSize == iInputPictureSize) || (aSize == iOutputPictureSize) )
+ {
+ iIntermediatePictureSize = aSize;
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::SetVideoPictureSinkOptionsL(), invalid intermediate size")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ break;
+
+ case EResampling:
+ {
+ // No need to check size, since it's iOutputPictureSize;
+ iIntermediatePictureSize = iOutputPictureSize;
+ }
+ break;
+
+ case EOperationNone:
+ {
+ // Operation is not set yet
+ User::Leave(KErrNotReady);
+ }
+ break;
+
+ default:
+ {
+ // Operation is not set yet
+ User::Leave(KErrNotReady);
+ break;
+ }
+ }
+
+ // Set picture sink
+ iPictureSink = aSink;
+ iPictureSinkTemp = aSink;
+ iPictureSinkEnabled = ETrue;
+ iPictureSinkClientSetting = ETrue;
+ iCurrentPictureSinkEnabled = ETrue;
+ iCurrentAsyncPictureSinkEnabled = ETrue;
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::UseDirectScreenAccessL
+// Requests using of DSA
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::UseDirectScreenAccessL(TBool /*aUseDSA*/, CFbsScreenDevice& /*aScreenDevice*/,
+ TTRDisplayOptions& /*aOptions*/)
+ {
+ // Not supported yet
+ User::Leave(KErrNotSupported);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::ParseMimeTypeL
+// Parses given MIME type
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::ParseMimeTypeL(const TDesC8& aMimeType, TBool aInOutMime)
+ {
+ TUint maxBitRate = 0;
+ TInt codecType = 0;
+ TBuf8<256> shortMimeType;
+ TBuf8<256> newMimeType;
+ TInt width = 0;
+ TUint codecLevel = 0;
+
+
+ if (aMimeType == KNullDesC8)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ if ( aMimeType.MatchF( _L8("*video/H263-2000*") ) != KErrNotFound )
+ {
+ // H.263
+ codecType = EH263;
+ shortMimeType = _L8("video/H263-2000");
+ newMimeType = shortMimeType;
+
+ if ( aMimeType.MatchF( _L8("*profile*") ) != KErrNotFound )
+ {
+ // Profile info is given, check it
+ if ( aMimeType.MatchF( _L8("*profile=0*") ) != KErrNotFound )
+ {
+ // Check level info
+ newMimeType += _L8("; profile=0");
+ }
+ else if ( aMimeType.MatchF( _L8("*profile=3*") ) != KErrNotFound )
+ {
+ // Check level info
+ newMimeType += _L8("; profile=3");
+ }
+ else
+ {
+ // We don't support any other profiles yet
+ PRINT((_L("CTRTranscoderImp::ParseMimeTypeL(), profile is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // Set defaults for profile=0;
+ newMimeType += _L8("; profile=0");
+ }
+
+
+ // Check level info
+ if ( aMimeType.MatchF( _L8("*level=*") ) != KErrNotFound )
+ {
+ if ( aMimeType.MatchF( _L8("*level=10*") ) != KErrNotFound )
+ {
+ // Set level=10;
+ maxBitRate = KTRMaxBitRateH263Level10;
+ codecLevel = KTRH263CodecLevel10;
+ newMimeType += _L8("; level=10");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=20*") ) != KErrNotFound )
+ {
+ // Set level=20;
+ maxBitRate = KTRMaxBitRateH263Level20;
+ codecLevel = KTRH263CodecLevel20;
+ newMimeType += _L8("; level=20");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=30*") ) != KErrNotFound )
+ {
+ // Set level=30;
+ maxBitRate = KTRMaxBitRateH263Level30;
+ codecLevel = KTRH263CodecLevel30;
+ newMimeType += _L8("; level=30");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=40*") ) != KErrNotFound )
+ {
+ // Set level=40;
+ maxBitRate = KTRMaxBitRateH263Level40;
+ codecLevel = KTRH263CodecLevel40;
+ newMimeType += _L8("; level=40");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=45*") ) != KErrNotFound )
+ {
+ // Set level=45;
+ maxBitRate = KTRMaxBitRateH263Level45;
+ codecLevel = KTRH263CodecLevel45;
+ newMimeType += _L8("; level=45");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=50*") ) != KErrNotFound )
+ {
+ // Set level=50;
+ maxBitRate = KTRMaxBitRateH263Level50;
+ codecLevel = KTRH263CodecLevel50;
+ newMimeType += _L8("; level=50");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=60*") ) != KErrNotFound )
+ {
+ // Set level=60;
+ maxBitRate = KTRMaxBitRateH263Level60;
+ codecLevel = KTRH263CodecLevel60;
+ newMimeType += _L8("; level=60");
+ }
+ else if ( aMimeType.MatchF( _L8("*level=70*") ) != KErrNotFound )
+ {
+ // Set level=70;
+ maxBitRate = KTRMaxBitRateH263Level70;
+ codecLevel = KTRH263CodecLevel70;
+ newMimeType += _L8("; level=70");
+ }
+ else
+ {
+ // We don't support any other levels
+ PRINT((_L("CTRTranscoderImp::ParseMimeTypeL(), level is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // Codec level is not specified, check requested picture size and set mime
+ if (aInOutMime)
+ {
+ width = iInputPictureSize.iWidth;
+ }
+ else
+ {
+ width = iOutputPictureSize.iWidth;
+ }
+
+ switch( width )
+ {
+ case KTRSubQCIFWidth:
+ case KTRQCIFWidth:
+ {
+ // Set defaults for level=10;
+ maxBitRate = KTRMaxBitRateH263Level10;
+ codecLevel = KTRH263CodecLevel10;
+ newMimeType += _L8("; level=10");
+ break;
+ }
+
+ case KTRCIFWidth:
+ {
+ // Set defaults for level=30;
+ maxBitRate = KTRMaxBitRateH263Level30;
+ codecLevel = KTRH263CodecLevel30;
+ newMimeType += _L8("; level=30");
+ break;
+ }
+
+ case KTRPALWidth:
+ {
+ // Set defaults for level=60;
+ maxBitRate = KTRMaxBitRateH263Level60;
+ codecLevel = KTRH263CodecLevel60;
+ newMimeType += _L8("; level=60");
+ break;
+ }
+
+ default:
+ {
+ // Set defaults for level=10;
+ maxBitRate = KTRMaxBitRateH263Level10;
+ codecLevel = KTRH263CodecLevel10;
+ newMimeType += _L8("; level=10");
+ break;
+ }
+ }
+ }
+ }
+ else if ( (aMimeType.MatchF( _L8("*video/H264*") ) != KErrNotFound) )
+ {
+ // H.264 (AVC)
+ codecType = EH264;
+ shortMimeType = _L8("video/H264");
+ newMimeType = shortMimeType;
+
+ // Check profile-level
+ if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
+ {
+ if ( aMimeType.MatchF( _L8("*profile-level-id=42800A*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level10;
+ codecLevel = KTRH264CodecLevel10;
+ newMimeType += _L8("; profile-level-id=42800A"); // Level 1
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level10b;
+ codecLevel = KTRH264CodecLevel10b;
+ newMimeType += _L8("; profile-level-id=42900B"); // Level 1b
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level11;
+ codecLevel = KTRH264CodecLevel11;
+ newMimeType += _L8("; profile-level-id=42800B"); // Level 1.1
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42800C*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level12;
+ codecLevel = KTRH264CodecLevel12;
+ newMimeType += _L8("; profile-level-id=42800C"); // Level 1.2
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42800D*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level13;
+ codecLevel = KTRH264CodecLevel13;
+ newMimeType += _L8("; profile-level-id=42800D"); // Level 1.3
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=428014*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level20;
+ codecLevel = KTRH264CodecLevel20;
+ newMimeType += _L8("; profile-level-id=428014"); // Level 2
+ }
+ //WVGA task
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=428015*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level21;
+ codecLevel = KTRH264CodecLevel21;
+ newMimeType += _L8("; profile-level-id=428015"); // Level 2.1
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=428016*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level22;
+ codecLevel = KTRH264CodecLevel22;
+ newMimeType += _L8("; profile-level-id=428016"); // Level 2.2
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42801E*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level30;
+ codecLevel = KTRH264CodecLevel30;
+ newMimeType += _L8("; profile-level-id=42801E"); // Level 3
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=42801F*") ) != KErrNotFound )
+ {
+ maxBitRate = KTRMaxBitRateH264Level31;
+ codecLevel = KTRH264CodecLevel31;
+ newMimeType += _L8("; profile-level-id=42801F"); // Level 3.1
+ }
+ else
+ {
+ // We don't support any other levels
+ PRINT((_L("CTRTranscoderImp::ParseMimeTypeL(), profile-level-id is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // profile-level-id is not specified, check requested picture size
+ if (aInOutMime)
+ {
+ width = iInputPictureSize.iWidth;
+ }
+ else
+ {
+ width = iOutputPictureSize.iWidth;
+ }
+
+ switch( width )
+ {
+ case KTRSubQCIFWidth:
+ case KTRQCIFWidth:
+ {
+ // Set level 1
+ maxBitRate = KTRMaxBitRateH264Level10;
+ codecLevel = KTRH264CodecLevel10;
+ newMimeType += _L8("; profile-level-id=42800A");
+ break;
+ }
+
+ case KTRQVGAWidth:
+ case KTRCIFWidth:
+ {
+ // Set level 1.2
+ maxBitRate = KTRMaxBitRateH264Level12;
+ codecLevel = KTRH264CodecLevel12;
+ newMimeType += _L8("; profile-level-id=42800C");
+ break;
+ }
+ case KTRWVGAWidth:
+ {
+ // Set level 3.1
+ maxBitRate = KTRMaxBitRateH264Level31;
+ codecLevel = KTRH264CodecLevel31;
+ newMimeType += _L8("; profile-level-id=42801F");
+ break;
+ }
+
+ default:
+ {
+ // Set level 1
+ maxBitRate = KTRMaxBitRateH264Level10;
+ codecLevel = KTRH264CodecLevel10;
+ newMimeType += _L8("; profile-level-id=42800A");
+ break;
+ }
+ }
+ }
+ }
+ else if ( (aMimeType.MatchF( _L8("*video/mp4v-es*") ) != KErrNotFound) ||
+ (aMimeType.MatchF( _L8("*video/MP4V-ES*") ) != KErrNotFound) )
+ {
+ // MPEG-4 Visual
+ codecType = EMpeg4;
+ shortMimeType = _L8("video/mp4v-es"); // Set short mime
+ newMimeType = shortMimeType;
+
+ // Check profile-level
+ if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
+ {
+ if ( aMimeType.MatchF( _L8("*profile-level-id=8*") ) != KErrNotFound )
+ {
+ // Set defaults for profile-level-id=8
+ newMimeType += _L8("; profile-level-id=8");
+ }
+ else if( aMimeType.MatchF( _L8("*profile-level-id=1*") ) != KErrNotFound )
+ {
+ // Set profile-level-id=1
+ maxBitRate = KTRMaxBitRateMPEG4Level1;
+ codecLevel = KTRMPEG4CodecLevel1;
+ newMimeType += _L8("; profile-level-id=1");
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=2*") ) != KErrNotFound )
+ {
+ // Set profile-level-id=2
+ maxBitRate = KTRMaxBitRateMPEG4Level2;
+ codecLevel = KTRMPEG4CodecLevel2;
+ newMimeType += _L8("; profile-level-id=2");
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=3*") ) != KErrNotFound )
+ {
+ // Set profile-level-id=3
+ maxBitRate = KTRMaxBitRateMPEG4Level3;
+ codecLevel = KTRMPEG4CodecLevel3;
+ newMimeType += _L8("; profile-level-id=3");
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=9*") ) != KErrNotFound )
+ {
+ // Set profile-level-id=9
+ maxBitRate = KTRMaxBitRateMPEG4Level0b;
+ codecLevel = KTRMPEG4CodecLevel0b;
+ newMimeType += _L8("; profile-level-id=9");
+ }
+ else if ( aMimeType.MatchF( _L8("*profile-level-id=4*") ) != KErrNotFound )
+ {
+ // Set profile-level-id=4
+ maxBitRate = KTRMaxBitRateMPEG4Level4a;
+ codecLevel = KTRMPEG4CodecLevel4a;
+ newMimeType += _L8("; profile-level-id=4");
+ }
+ else
+ {
+ // We don't support any other levels
+ PRINT((_L("CTRTranscoderImp::ParseMimeTypeL(), profile-level-id is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else
+ {
+ // profile-level-id is not specified, check requested picture size
+ // Set defaults for profile-level-id=8
+ if (aInOutMime)
+ {
+ width = iInputPictureSize.iWidth;
+ }
+ else
+ {
+ width = iOutputPictureSize.iWidth;
+ }
+
+ switch( width )
+ {
+ case KTRSubQCIFWidth:
+ case KTRQCIFWidth:
+ {
+ // Set profile-level-id=0
+ codecLevel = KTRMPEG4CodecLevel0;
+ maxBitRate = KTRMaxBitRateMPEG4Level0;
+ newMimeType += _L8("; profile-level-id=8");
+ break;
+ }
+
+ case KTRQVGAWidth:
+ case KTRCIFWidth:
+ {
+ // Set profile-level-id=3
+ maxBitRate = KTRMaxBitRateMPEG4Level3;
+ codecLevel = KTRMPEG4CodecLevel3;
+ newMimeType += _L8("; profile-level-id=3");
+ break;
+ }
+
+ case KTRVGAWidth:
+ {
+ // Set profile-level-id=4 (4a)
+ maxBitRate = KTRMaxBitRateMPEG4Level4a;
+ codecLevel = KTRMPEG4CodecLevel4a;
+ newMimeType += _L8("; profile-level-id=4");
+ break;
+ }
+
+ default:
+ {
+ // Set profile-level-id=0
+ maxBitRate = KTRMaxBitRateMPEG4Level0;
+ codecLevel = KTRMPEG4CodecLevel0;
+ newMimeType += _L8("; profile-level-id=8");
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::ParseMimeL(), there is curently no support for this type")))
+ User::Leave(KErrNotSupported);
+ }
+
+ if (aInOutMime)
+ {
+ // Mime type was set for Input format
+ iInputCodecLevel = codecLevel;
+ iInputCodec = codecType;
+ iInputMaxBitRate = maxBitRate;
+
+ iInputMimeType = newMimeType;
+ iInputShortMimeType = shortMimeType;
+ }
+ else
+ {
+ // Mime type was set for Output format
+ iOutputCodecLevel = codecLevel;
+ iOutputCodec = codecType;
+ iOutputMaxBitRate = maxBitRate;
+
+ iOutputMimeType = newMimeType;
+ iOutputShortMimeType = shortMimeType;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::IsValid
+// Checks whether the size is valid
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CTRTranscoderImp::IsValid(TSize& aSize)
+ {
+ TBool valid = EFalse;
+
+ switch(aSize.iWidth)
+ {
+ case KTRSubQCIFWidth:
+ {
+ if (aSize.iHeight == KTRSubQCIFHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTRQCIFWidth:
+ {
+ if (aSize.iHeight == KTRQCIFHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTRCIFWidth:
+ {
+ if (aSize.iHeight == KTRCIFHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTRQVGAWidth:
+ {
+ if (aSize.iHeight == KTRQVGAHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTRVGAWidth:
+ {
+ if (aSize.iHeight == KTRVGAHeight || aSize.iHeight == KTRVGA16By9Height)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+ case KTRWVGAWidth:
+ {
+ if (aSize.iHeight == KTRWVGAHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTR4CIFWidth:
+ {
+ if (aSize.iHeight == KTR4CIFHeight)
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ case KTRPALWidth:
+ {
+ if ( (aSize.iHeight == KTRPAL2Height) || (aSize.iHeight == KTRPAL1Height) )
+ {
+ valid = ETrue;
+ }
+ break;
+ }
+
+ default:
+ {
+ valid = EFalse;
+ }
+ }
+
+ return valid;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetVideoBitRateL
+// Gets video bitrate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CTRTranscoderImp::GetVideoBitRateL()
+ {
+ if (iVideoEncoderClient)
+ {
+ return iVideoEncoderClient->GetVideoBitRateL();
+ }
+
+ // Otherwise return 0, in case if it's called before initializing or in different operating mode
+ // e.g. (without encoding)
+ return 0;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetFrameRateL
+// Gets frame rate
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TReal CTRTranscoderImp::GetFrameRateL()
+ {
+ if (iVideoEncoderClient)
+ {
+ return iVideoEncoderClient->GetFrameRateL();
+ }
+
+ // Otherwise return 0, in case if it's called before initializing or in different operating mode
+ // e.g. (without encoding)
+ return 0;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetVideoCodecL
+// Gets current video codec in use
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::GetVideoCodecL(TDes8& aVideoMimeType)
+ {
+ if (iState == ETRNone)
+ {
+ aVideoMimeType = KNullDesC8;
+ }
+ else
+ {
+ aVideoMimeType = iOutputShortMimeType;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetTranscodedPictureSizeL
+// Gets output transcoded picture size
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::GetTranscodedPictureSizeL(TSize& aSize)
+ {
+ aSize = iOutputPictureSize;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::InitializeL
+// Initializes transcider
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::InitializeL()
+ {
+ PRINT((_L("CTRTranscoderImp::InitializeL(), In")))
+ TInt status = KErrNone;
+
+
+ if (iState != ETROpened)
+ {
+ PRINT((_L("CTRTranscoderImp::InitializeL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ iVideoDecoderClient->InitializeL();
+
+ // Check encoder client if it supports optimized data transfer
+ TRAP( status, iVideoEncoderClient->UseDataTransferOptimizationL() );
+ if (status == KErrNone)
+ {
+ iOptimizedDataTransfer = ETrue;
+ }
+
+ TRAP(status, iVideoEncoderClient->InitializeL());
+
+ if (status != KErrNone)
+ {
+ iEncoderInitStatus = status;
+ InitComplete();
+ }
+
+ break;
+ }
+
+ case EDecoding:
+ {
+ iEncoderInitStatus = KErrNone;
+ iVideoDecoderClient->InitializeL();
+ break;
+ }
+
+ case EEncoding:
+ {
+ iDecoderInitStatus = KErrNone;
+ iVideoEncoderClient->InitializeL();
+ break;
+ }
+
+ case EResampling:
+ {
+ // Resampler is already created
+ iState = ETRInitialized;
+ iObserver.MtroInitializeComplete(KErrNone);
+ return;
+ }
+
+ default:
+ {
+ // Transcoder is not ready to be initialized
+ User::Leave(KErrNotReady);
+ break;
+ }
+ }
+
+ PRINT((_L("CTRTranscoderImp::InitializeL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoEncInitializeComplete
+// Encoder initializing is completed with aError
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoEncInitializeComplete(TInt aError)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncInitializeComplete(), status[%d]"), aError))
+
+ if (aError == KErrHardwareNotAvailable)
+ {
+ // Encoder needs to be reinitialized
+
+ // Check if encoder client supports optimized data transfer
+ iOptimizedDataTransfer = EFalse;
+ TRAPD( status, iVideoEncoderClient->UseDataTransferOptimizationL() );
+ if (status == KErrNone)
+ {
+ iOptimizedDataTransfer = ETrue;
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncInitializeComplete(), Trying to reinitialize encoder")))
+ TRAP(status, iVideoEncoderClient->InitializeL());
+
+ if (status == KErrNone)
+ {
+ // Reinitialization done so wait for the next initialize complete call
+ return;
+ }
+ }
+
+ iEncoderInitStatus = aError;
+ this->InitComplete();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoDecInitializeComplete
+// Decoder initializing is completed with aError
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoDecInitializeComplete(TInt aError)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecInitializeComplete(), status[%d]"), aError))
+
+ if (aError == KErrHardwareNotAvailable)
+ {
+ // Decoder needs to be reinitialized
+
+ // Check if decoder supports scaling
+ iDecodedPictureSize = iInputPictureSize;
+
+ // Set to default
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingDefault;
+
+ TBool srcWide = iScaler->IsWideAspectRatio(iInputPictureSize);
+ TBool dstWide = iScaler->IsWideAspectRatio(iOutputPictureSize);
+
+ if (srcWide != dstWide)
+ {
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecInitializeComplete(), black boxing needed")))
+
+ // get intermediate resolution from scaler
+ TSize resolution;
+ TSize bb = TSize(0,0);
+
+ TBool scale = iScaler->GetIntermediateResolution(iInputPictureSize, iOutputPictureSize,
+ resolution, bb);
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecInitializeComplete(), int. resolution (%d, %d), scale = %d"),
+ resolution.iWidth, resolution.iHeight, TInt(scale)))
+
+ if (scale && iVideoDecoderClient->SetDecoderScaling(iInputPictureSize, resolution))
+ {
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecInitializeComplete(), decoder scaling supported")))
+
+ iDecodedPictureSize = resolution;
+ //iDecodedPictureSize = iOutputPictureSize;
+
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingScaling;
+ }
+ }
+
+ else if (iVideoDecoderClient->SetDecoderScaling(iInputPictureSize, iOutputPictureSize))
+ {
+ // Scaling is supported
+ iDecodedPictureSize = iOutputPictureSize;
+
+ iMaxFramesInProcessing = KTRMaxFramesInProcessingScaling;
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecInitializeComplete(), Trying to reinitialize decoder")))
+ TRAPD(status, iVideoDecoderClient->InitializeL());
+
+ if (status == KErrNone)
+ {
+ // Reinitialization done so wait for the next initialize complete call
+ return;
+ }
+ }
+
+ iDecoderInitStatus = aError;
+ this->InitComplete();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::InitComplete
+// Checks and reports init status to the client
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::InitComplete()
+ {
+ TInt status = KErrNone;
+
+ if ( (iEncoderInitStatus != KTRErrNotReady) && (iDecoderInitStatus != KTRErrNotReady) )
+ {
+ // Both were initialized, check statuses
+ if ( (iEncoderInitStatus == KErrNone) && (iDecoderInitStatus == KErrNone) )
+ {
+ // Both are ok,
+ // Allocate buffers for intrnal use
+ TRAP( status, this->AllocateBuffersL() );
+
+ if (status == KErrNone)
+ {
+ iState = ETRInitialized;
+ }
+
+ // Inform the client
+ iObserver.MtroInitializeComplete(status);
+ }
+ else if (iDecoderInitStatus == KErrNone)
+ {
+ // Report encoder init error
+ iObserver.MtroInitializeComplete(iEncoderInitStatus);
+ }
+ else
+ {
+ // Report decoder init error
+ iObserver.MtroInitializeComplete(iDecoderInitStatus);
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::StartL
+// Starts data processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::StartL()
+ {
+ if ( (iState == ETRInitialized) || (iState == ETRStopped) )
+ {
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ // Reset flag here
+ iAsyncStop = EFalse;
+
+ iVideoDecoderClient->StartL();
+
+ if (!iBitRateSetting)
+ {
+ this->SetVideoBitRateL(iOutputMaxBitRate);
+ }
+
+ iVideoEncoderClient->StartL();
+ }
+ break;
+
+ case EDecoding:
+ {
+ iVideoDecoderClient->StartL();
+ }
+ break;
+
+ case EEncoding:
+ {
+ if (!iBitRateSetting)
+ {
+ this->SetVideoBitRateL(iOutputMaxBitRate);
+ }
+
+ iVideoEncoderClient->StartL();
+ }
+ break;
+
+ case EResampling:
+ {
+ // Nothing to do
+ }
+ break;
+
+ default:
+ {
+ // Should never be reached
+ TRASSERT(0);
+ }
+ }
+
+ iState = ETRRunning;
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::StartL(), called in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::AllocateBuffersL
+// Allocates internal buffers
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::AllocateBuffersL()
+ {
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), In")))
+ TInt i = 0;
+ TUint dataBufferSize = 0;
+
+
+ // Assume we are using 420 as a middle temporal format
+ dataBufferSize = iOutputPictureSize.iWidth * iOutputPictureSize.iHeight * 3 / 2;
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), data buffer size[%d]"), dataBufferSize))
+
+ // Allocate TVideoPicture containers
+ iVideoPictureArray = new (ELeave) TVideoPicture[ KTRPictureBuffersNumber ];
+
+ for (i = 0; i < KTRPictureBuffersNumber; i ++)
+ {
+ // Reset iRawData ptr
+ iVideoPictureArray[i].iData.iRawData = NULL;
+ }
+
+ switch (iMode)
+ {
+ case EFullTranscoding:
+ {
+ // Allocate TTRVideoPicture containers (since the client requested to provide
+ // intermediate trancsoded content )
+ iTRVideoPictureArray = new (ELeave)TTRVideoPicture[KTRPictureContainersNumber];
+
+ // Add TR picture containers to the queue
+ for (i = 0; i < KTRPictureContainersNumber; i ++)
+ {
+ iTranscoderTRPictureQueue.AddLast( iTRVideoPictureArray[i] );
+ }
+
+ if (iOptimizedDataTransfer)
+ {
+ // If optimized data transfer is used, no other allocations required.
+ return;
+ }
+ }
+ break;
+
+ case EDecoding:
+ {
+ if ( iDecodedPictureSize == iOutputPictureSize )
+ {
+ // Resampling and data allocation is not required
+ return;
+ }
+ }
+ break;
+
+ case EEncoding:
+ {
+ if ( iInputPictureSize == iOutputPictureSize )
+ {
+ // Allocation data buffers for iVideoPictureArray is not needed, TVideoPicture
+ // containers are enough in this case. Initialize the queue
+ for (i = 0; i < KTRPictureBuffersNumber; i ++)
+ {
+ iTranscoderPictureQueue.AddLast( iVideoPictureArray[i] );
+ }
+
+ return;
+ }
+ }
+ break;
+
+ case EResampling:
+ {
+ // Nothing to do
+ return;
+ }
+
+ default:
+ {
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), Not ready, mode[%d]"), iMode))
+ User::Leave(KErrNotReady);
+ }
+ break;
+ }
+
+ // Common part
+ // Allocate data buffers
+ iDataArray = new (ELeave) TUint8*[ KTRPictureBuffersNumber ];
+
+ for ( i = 0; i < KTRPictureBuffersNumber; i ++ )
+ {
+ iDataArray[i] = NULL;
+ }
+
+ for ( i = 0; i < KTRPictureBuffersNumber; i ++ )
+ {
+ iDataArray[i] = new (ELeave) TUint8[dataBufferSize];
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), data buffer[%d], [0x%x], allocated"), i, iDataArray[i]))
+ }
+
+ // Initialize the queue
+ for ( i = 0; i < KTRPictureBuffersNumber; i ++ )
+ {
+ iVideoPictureArray[i].iData.iRawData = new (ELeave) TPtr8(0, 0, 0);
+ iVideoPictureArray[i].iData.iRawData->Set(iDataArray[i], dataBufferSize, dataBufferSize);
+ iVideoPictureArray[i].iData.iDataSize.SetSize(iOutputPictureSize.iWidth,
+ iOutputPictureSize.iHeight);
+ iTranscoderPictureQueue.AddLast( iVideoPictureArray[i] );
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), picture[%d], added to the queue"), i))
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), picture data[0x%x]"),
+ iVideoPictureArray[i].iData.iRawData->Ptr() ))
+ }
+
+ PRINT((_L("CTRTranscoderImp::AllocateBuffersL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::WriteCodedBufferL
+// Writes coded buffer to transcoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::WriteCodedBufferL(CCMRMediaBuffer* aBuffer)
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), In")))
+ CTREventItem* newEvent = NULL;
+
+ if (!aBuffer)
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), Client sends invalid data")))
+ User::Leave(KErrArgument);
+ }
+
+ if (iState == ETRRunning)
+ {
+ if (iSetRandomAccessPoint)
+ {
+ // Get new item from the eventsrc
+ if (!iTranscoderEventSrc.IsEmpty())
+ {
+ newEvent = iTranscoderEventSrc.First();
+ newEvent->iLink.Deque();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), iTranscoderEventSrc queue is empty, abort")))
+ iObserver.MtroFatalError(KErrAbort);
+ return;
+ }
+
+ if (newEvent)
+ {
+ newEvent->iTimestamp = aBuffer->TimeStamp();
+ newEvent->iRandomAccessStatus = ETrue;
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), picture[%f] RandomAccess"), I64REAL(aBuffer->TimeStamp().Int64()) ))
+ }
+
+ iSetRandomAccessPoint = EFalse;
+ }
+
+ if (iPictureSinkSettingChanged)
+ {
+ if (!newEvent)
+ {
+ // Get new item from the event src queue
+ if (!iTranscoderEventSrc.IsEmpty())
+ {
+ newEvent = iTranscoderEventSrc.First();
+ newEvent->iLink.Deque();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), iTranscoderEventSrc queue is empty, abort")))
+ iObserver.MtroFatalError(KErrAbort);
+ return;
+ }
+ }
+
+ if (newEvent)
+ {
+ newEvent->iTimestamp = aBuffer->TimeStamp();
+ newEvent->iEnablePictureSinkStatus = ETrue;
+ newEvent->iEnablePictureSinkClientSetting = iPictureSinkClientSetting;
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), picture[%f] PS[%d]"), I64REAL(aBuffer->TimeStamp().Int64()), iPictureSinkClientSetting ))
+ }
+
+ // Reset change flag
+ iPictureSinkSettingChanged = EFalse;
+ }
+
+ // encoder enabled / disabled
+ if (iEncoderEnabledSettingChanged)
+ {
+ if (!newEvent)
+ {
+ // Get new item from the eventsrc
+ if (!iTranscoderEventSrc.IsEmpty())
+ {
+ newEvent = iTranscoderEventSrc.First();
+ newEvent->iLink.Deque();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), iTranscoderEventSrc queue is empty, abort")))
+ iObserver.MtroFatalError(KErrAbort);
+ return;
+ }
+ }
+
+ if (newEvent)
+ {
+ newEvent->iTimestamp = aBuffer->TimeStamp();
+ newEvent->iEnableEncoderStatus = ETrue;
+ newEvent->iEnableEncoderClientSetting = iEncoderEnableClientSetting;
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), picture[%f] Enc[%d]"), I64REAL(aBuffer->TimeStamp().Int64()), iEncoderEnableClientSetting ))
+ }
+
+ // Reset change flag
+ iEncoderEnabledSettingChanged = EFalse;
+ }
+
+ if (newEvent)
+ {
+ // Put it to transcoder event queue
+ iTranscoderEventQueue.AddLast(*newEvent);
+ }
+
+ // Write buffer to DecoderClient
+ iVideoDecoderClient->WriteCodedBufferL(aBuffer);
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ PRINT((_L("CTRTranscoderImp::WriteCodedBufferL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtroReturnCodedBuffer
+// Returns coded buffer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoReturnCodedBuffer(CCMRMediaBuffer* aBuffer)
+ {
+ iObserver.MtroReturnCodedBuffer(aBuffer);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoNewPicture
+// New decoded picture is available
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoNewPicture(TVideoPicture* aDecodedPicture)
+ {
+ TInt status = KErrNone;
+ TVideoPicture* picture = NULL;
+ CTREventItem* nextEvent = NULL;
+ MTRVideoPictureSink* pictureSink = iPictureSinkTemp; //
+ TBool pictureSinkEnabled = iCurrentPictureSinkEnabled;
+ TBool encoderEnabled = iCurrentEncoderEnabled;
+
+ if (iState == ETRFatalError)
+ {
+ // Nothing to do
+ return;
+ }
+
+ if (!aDecodedPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), decoded picture is not valid")))
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+ else if (!aDecodedPicture->iData.iRawData)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), picture raw data is not valid")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), decoded picture timestamp [%f]"), I64REAL(aDecodedPicture->iTimestamp.Int64()) ))
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ if ( !iNewEvent && !iTranscoderEventQueue.IsEmpty() )
+ {
+ // Get new event
+ iNewEvent = iTranscoderEventQueue.First();
+ iNewEvent->iLink.Deque();
+
+ // Check the next event if there are any
+ if (!iTranscoderEventQueue.IsEmpty())
+ {
+ nextEvent = iTranscoderEventQueue.First();
+
+ if (aDecodedPicture->iTimestamp >= nextEvent->iTimestamp)
+ {
+ // Should not happen normally, indicate an error
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Previous event was not handled properly, abort data processing")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+ }
+ }
+
+ if (iNewEvent)
+ {
+ // Check timestamp for this event
+ if (aDecodedPicture->iTimestamp >= iNewEvent->iTimestamp)
+ {
+ // Perform requested client's operation
+ // 1. PictureSinkStatus
+ if (iNewEvent->iEnablePictureSinkStatus)
+ {
+ pictureSinkEnabled = iNewEvent->iEnablePictureSinkClientSetting;
+ }
+
+ // 2. EnableEncoderStatus
+ if (iNewEvent->iEnableEncoderStatus)
+ {
+ encoderEnabled = iNewEvent->iEnableEncoderClientSetting;
+ }
+
+ // 3. Random access
+ if (iNewEvent->iRandomAccessStatus)
+ {
+ iCurrentRandomAccess = iNewEvent->iRandomAccessStatus;
+ }
+
+ // This event is already handled, it's not new anymore
+ if (!pictureSinkEnabled && !encoderEnabled)
+ {
+ // Picture is returned to decoder, we don't need any actions for that
+ iNewEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iNewEvent);
+ }
+ else if (pictureSinkEnabled)
+ {
+ if (iIntermediatePictureSize == iDecodedPictureSize)
+ {
+ // Picture is sent to the client first, decoded picture is not returned
+ // to decoder until it's hold by the client.
+ // No new events are handled here, act according global settings.
+ iNewEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iNewEvent);
+ }
+ else
+ {
+ // Picture is processed acynchronously first
+ iTranscoderAsyncEventQueue.AddLast(*iNewEvent);
+
+ // Keep previous current global setting
+ iCurrentAsyncPictureSinkEnabled = iCurrentPictureSinkEnabled;
+ iCurrentAsyncEncoderEnabled = iCurrentEncoderEnabled;
+ }
+ }
+ else // encoderEnabled otherwise
+ {
+ // Picture is processed acynchronously first
+ iTranscoderAsyncEventQueue.AddLast(*iNewEvent);
+
+ // Keep previous current global setting
+ iCurrentAsyncPictureSinkEnabled = iCurrentPictureSinkEnabled;
+ iCurrentAsyncEncoderEnabled = iCurrentEncoderEnabled;
+ }
+
+ // Reset new event
+ iNewEvent = NULL;
+
+ // Update current settings
+ iCurrentPictureSinkEnabled = pictureSinkEnabled;
+ iCurrentEncoderEnabled = encoderEnabled;
+ }
+ }
+
+ // Settings now defined, act accordingly
+ if (!pictureSinkEnabled && !encoderEnabled)
+ {
+ // Nothing to do with this picture, return it to decoder
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), return picture[%f] to decoder"), I64REAL(aDecodedPicture->iTimestamp.Int64()) ))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ return;
+ }
+
+ if (pictureSinkEnabled)
+ {
+ pictureSink = iPictureSinkTemp;
+
+ if (!pictureSink)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), picture sink was not set, report to client!")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrNotReady);
+ return;
+ }
+ }
+ else
+ {
+ pictureSink = NULL;
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), PS[%d], Enc[%d], RandAcc[%d] for [%f]"), pictureSinkEnabled, encoderEnabled, iCurrentRandomAccess, I64REAL(aDecodedPicture->iTimestamp.Int64()) ))
+
+ if ( pictureSink && (iIntermediatePictureSize == iDecodedPictureSize) )
+ {
+ // Since the client requested to provide initial decoded picture, send
+ // it first, and only then resample and encode. (See SendPictureToTranscoder)
+ if (!iTranscoderTRPictureQueue.IsEmpty())
+ {
+ TTRVideoPicture* pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+ pictureToClient->iRawData = aDecodedPicture->iData.iRawData;
+ pictureToClient->iDataSize = aDecodedPicture->iData.iDataSize;
+ pictureToClient->iTimestamp = aDecodedPicture->iTimestamp;
+
+ // Store picture until it's returned from the client
+ iDecodedPicture = aDecodedPicture;
+
+ // Deliver picture to the client
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), send picture to the client via sink")))
+ pictureSink->MtroPictureFromTranscoder(pictureToClient);
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), iTranscoderTRPictureQueue is empty, abort operation")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrAbort);
+ }
+
+ return;
+ }
+
+ if (iOptimizedDataTransfer)
+ {
+ // We need a new picture buffer every time !!!
+ if ( !iCIPictureBuffersQueue.IsEmpty() )
+ {
+ picture = iCIPictureBuffersQueue.First();
+ picture->iLink.Deque();
+ }
+ else
+ {
+ TRAP( status, picture = iVideoEncoderClient->GetTargetVideoPictureL() );
+ }
+
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), GetTargetVideoPictureL failed [%d]"), status))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(status);
+ return;
+ }
+ else if (picture)
+ {
+ // Set options for picture
+ picture->iData.iDataSize = iOutputPictureSize;
+
+ // we don't support resampling for 422, set default for 420 length
+ // Add check of output data format (422 or 420) in the future and set dataLength properly
+ TInt length = iOutputPictureSize.iWidth * iOutputPictureSize.iHeight * 3 / 2;
+
+ if ( length > picture->iData.iRawData->MaxLength() )
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), length exceeds CI buffer maxlength[%d, %d]"), length, picture->iData.iRawData->MaxLength() ))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrGeneral);
+ return;
+ }
+
+ // set length
+ picture->iData.iRawData->SetLength(length);
+ }
+ else
+ {
+ if (iRealTime) // (picture is not available, act according realtime mode)
+ {
+ // Picture buffer is not available from encoder hwdevice
+ // return decoded picture back, otherwise suspend decoding..
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Picture buffer is not available through CI, Drop") ))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ return;
+ }
+ else
+ {
+ // Keep picture and does not return it to DecoderClient before processing
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Picture buffer is not available through CI, store") ))
+ iWaitNewDecodedPicture = aDecodedPicture;
+ return;
+ }
+ }
+ }
+ else
+ {
+ if (!iTranscoderPictureQueue.IsEmpty())
+ {
+ picture = iTranscoderPictureQueue.First();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), iTranscoderPictureQueue is empty")))
+
+ if (iRealTime) // (picture is not available, act according realtime mode)
+ {
+ // Picture buffer is not available from encoder hwdevice
+ // return decoded picture back, otherwise suspend decoding..
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Picture buffer is not available fromEncoder, Drop") ))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ return;
+ }
+ else
+ {
+ // Keep picture and does not return it to DecoderClient before processing
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Picture buffer is not available fromEncoder, store") ))
+ iWaitNewDecodedPicture = aDecodedPicture;
+ return;
+ }
+ }
+ }
+
+ if (picture)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), picture[0x%x], data[0x%x]"),
+ picture, picture->iData.iRawData->Ptr() ))
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), decPicture[0x%x], data[0x%x]"),
+ aDecodedPicture, aDecodedPicture->iData.iRawData->Ptr() ))
+
+ // Resample this picture
+ TRAP(status, iScaler->SetScalerOptionsL( *(aDecodedPicture->iData.iRawData), *(picture->iData.iRawData),
+ aDecodedPicture->iData.iDataSize, picture->iData.iDataSize ) );
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Set scaler options failed[%d]"), status))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(status);
+ return;
+ }
+
+ if (!iOptimizedDataTransfer)
+ {
+ // Remove picture from transcoder queue
+ picture->iLink.Deque();
+ }
+
+ // Scale
+ iScaler->Scale();
+ picture->iData.iDataFormat = EYuvRawData;
+ picture->iTimestamp = aDecodedPicture->iTimestamp;
+
+ // Put resampled picture to encoder queue
+ iEncoderPictureQueue.AddLast(*picture);
+
+ // Make request to process this picture
+ this->DoRequest();
+
+ // Return used picture to decoder
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Transcoder picture queue is empty, skip this buffer")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ }
+ }
+ break;
+
+ case EDecoding:
+ {
+ if (!iPictureSink)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), iPictureSink was not set")))
+ iObserver.MtroFatalError(KErrNotReady);
+ return;
+ }
+
+ if (aDecodedPicture->iData.iDataSize.iWidth != iDecodedPictureSize.iWidth ||
+ aDecodedPicture->iData.iDataSize.iHeight != iDecodedPictureSize.iHeight )
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), picture size is not valid")))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+
+ // Store picture until it's returned from the client
+ iDecodedPicture = aDecodedPicture;
+
+ if (iDecodedPictureSize == iOutputPictureSize)
+ {
+ // Send picture directly to the client
+ iPicureToClient.iRawData = aDecodedPicture->iData.iRawData;
+ iPicureToClient.iDataSize = aDecodedPicture->iData.iDataSize;
+ iPicureToClient.iTimestamp = aDecodedPicture->iTimestamp;
+ iPictureSink->MtroPictureFromTranscoder(&iPicureToClient);
+ }
+ else
+ {
+ // Resample this picture to desired size and send to the client
+ if ( !iTranscoderPictureQueue.IsEmpty() )
+ {
+ iVideoPictureTemp = iTranscoderPictureQueue.First();
+ iVideoPictureTemp->iLink.Deque();
+
+ // Resample this picture
+ TRAP(status, iScaler->SetScalerOptionsL( *(aDecodedPicture->iData.iRawData), *(iVideoPictureTemp->iData.iRawData),
+ aDecodedPicture->iData.iDataSize, iVideoPictureTemp->iData.iDataSize ) );
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), Set scaler options failed[%d]"), status))
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+ iObserver.MtroFatalError(status);
+ return;
+ }
+
+ iScaler->Scale();
+ iPicureToClient.iRawData = iVideoPictureTemp->iData.iRawData;
+ iPicureToClient.iDataSize = iVideoPictureTemp->iData.iDataSize;
+ iPicureToClient.iTimestamp = aDecodedPicture->iTimestamp;
+
+ // Return decoded picture to decoder
+ iVideoDecoderClient->ReturnPicture(aDecodedPicture);
+
+ // Sent picture to the client
+ iPictureSink->MtroPictureFromTranscoder(&iPicureToClient);
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewPicture(), observer should not be called in this mode")))
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::DoRequest
+// Makes a new request
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::DoRequest()
+ {
+ if ( !this->IsActive() )
+ {
+ this->SetActive();
+ iStat = &iStatus;
+ User::RequestComplete( iStat, KErrNone );
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::DoRequest(), AO is already active")))
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::RunL
+// CActive's RunL implementation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::RunL()
+ {
+ PRINT((_L("CTRTranscoderImp::RunL(), In")))
+ TVideoPicture* picture = NULL;
+ MTRVideoPictureSink* pictureSink = iPictureSinkTemp;
+ TBool pictureSinkEnabled = iCurrentAsyncPictureSinkEnabled;
+ TBool encoderEnabled = iCurrentAsyncEncoderEnabled;
+ TBool randomAccess = EFalse;
+
+
+ if ( !iEncoderPictureQueue.IsEmpty() )
+ {
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ // Encode all pictures in the queue
+ TInt count = 0;
+
+
+ while ( !iEncoderPictureQueue.IsEmpty() )
+ {
+ PRINT((_L("CTRTranscoderImp::RunL(), count[%d]"), count))
+ count ++;
+ picture = iEncoderPictureQueue.First();
+
+ // Check event queue
+ if (!iAsyncEvent && !iTranscoderAsyncEventQueue.IsEmpty())
+ {
+ // Trasnscoder configuration is unknown, handle new event
+ iAsyncEvent = iTranscoderAsyncEventQueue.First();
+ iAsyncEvent->iLink.Deque();
+ }
+
+ if (iAsyncEvent)
+ {
+ // Check timestamp for this event
+ if (picture->iTimestamp >= iAsyncEvent->iTimestamp)
+ {
+ // Perform requested client's operation
+ // 1. PictureSinkStatus
+ if (iAsyncEvent->iEnablePictureSinkStatus)
+ {
+ pictureSinkEnabled = iAsyncEvent->iEnablePictureSinkClientSetting;
+ }
+
+ // 2. EnableEncoderStatus
+ if (iAsyncEvent->iEnableEncoderStatus)
+ {
+ encoderEnabled = iAsyncEvent->iEnableEncoderClientSetting;
+ }
+
+ // 3. RandomAccess
+ if (iAsyncEvent->iRandomAccessStatus)
+ {
+ randomAccess = iAsyncEvent->iRandomAccessStatus;
+ }
+
+ // This event is already handled, we don't need it anymore
+ iAsyncEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iAsyncEvent);
+ iAsyncEvent = NULL;
+
+ // Update current settings
+ iCurrentAsyncPictureSinkEnabled = pictureSinkEnabled;
+ iCurrentAsyncEncoderEnabled = encoderEnabled;
+ iCurrentAsyncRandomAccess = randomAccess;
+ }
+ }
+ // Else: Event queue is empty, act according async global options
+
+ // Settings now defined, act accordingly
+ PRINT((_L("CTRTranscoderImp::RunL(), PS[%d], Enc[%d], RandAcc[%d] for [%f]"),
+ pictureSinkEnabled, encoderEnabled, randomAccess, I64REAL(picture->iTimestamp.Int64()) ))
+
+ if (pictureSinkEnabled)
+ {
+ if (!pictureSink)
+ {
+ PRINT((_L("CTRTranscoderImp::RunL(), Picture sink was not set, time to panic")))
+ TRASSERT(0);
+ }
+
+ // Send decoded picture to the client first, and encode it after returning
+ if (!iTranscoderTRPictureQueue.IsEmpty())
+ {
+ picture->iLink.Deque();
+
+ TTRVideoPicture* pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+ pictureToClient->iRawData = picture->iData.iRawData;
+ pictureToClient->iDataSize = picture->iData.iDataSize;
+ pictureToClient->iTimestamp = picture->iTimestamp;
+
+ // Keep TVideoPicture container to the iContainerWaitQueue until the picture is returned back.
+ iContainerWaitQueue.AddLast(*picture);
+
+ // Deliver picture to the client
+ pictureSink->MtroPictureFromTranscoder(pictureToClient);
+ //
+ // return;
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::RunL(), iTranscoderTRPictureQueue is empty, abort")))
+ iObserver.MtroFatalError(KErrAbort);
+ return;
+ }
+ }
+ else if (!encoderEnabled)
+ {
+ // All picture in this queue must be encoded
+ PRINT((_L("CTRTranscoderImp::RunL(), All pictures from iEncoderPictureQueue must be encoded, error!")))
+ TRASSERT(0);
+ }
+ else
+ {
+ // Send picture to encoder
+ picture = iEncoderPictureQueue.First();
+ picture->iLink.Deque();
+
+ if (randomAccess)
+ {
+ iVideoEncoderClient->SetRandomAccessPoint();
+ randomAccess = EFalse;
+ }
+
+ iVideoEncoderClient->EncodePictureL(picture);
+ }
+ } // END while loop
+ }
+ break;
+
+ case EDecoding:
+ {
+ // Send decoded picture to the client.
+ if (!iTranscoderTRPictureQueue.IsEmpty())
+ {
+ picture = iEncoderPictureQueue.First();
+ picture->iLink.Deque();
+
+ // Take Transcoder picture container
+ TTRVideoPicture* pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+
+ pictureToClient->iRawData = picture->iData.iRawData;
+ pictureToClient->iDataSize = picture->iData.iDataSize;
+ pictureToClient->iTimestamp = picture->iTimestamp;
+
+ if (iPictureSink)
+ {
+ iPictureSink->MtroPictureFromTranscoder(pictureToClient);
+ }
+ else
+ {
+ // Should not happen
+ PRINT((_L("CTRTranscoderImp::RunL(), Decoding, PictureSink is not valid")))
+ TRASSERT(0);
+ }
+
+ // Keep TVideoPicture container to the iContainerWaitQueue until the picture is returned back.
+ iContainerWaitQueue.AddLast(*picture);
+ }
+ }
+ break;
+
+ case EEncoding:
+ {
+ // Send picture to video encoder
+ if ( !iEncoderPictureQueue.IsEmpty() )
+ {
+ picture = iEncoderPictureQueue.First();
+ picture->iLink.Deque();
+ iVideoEncoderClient->EncodePictureL(picture);
+ }
+ }
+ break;
+
+ case EResampling:
+ {
+ PRINT((_L("CTRTranscoderImp::RunL(), should not be called in Resampling mode")))
+ TRASSERT(0);
+ }
+ break;
+
+ case EOperationNone:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+
+ default:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+ }
+ }
+
+ PRINT((_L("CTRTranscoderImp::RunL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::DoCancel
+// Cancel
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::DoCancel()
+ {
+ // Nothing to do
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::RunError
+// Handles AO leave
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CTRTranscoderImp::RunError(TInt aError)
+ {
+ PRINT((_L("CTRTranscoderImp::RunError(), seems RunL leaved, error[%d]."), aError))
+
+ iObserver.MtroFatalError(aError);
+
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoEncoderReturnPicture
+// Returns picture from encoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoEncoderReturnPicture(TVideoPicture* aPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture()")))
+ TTRVideoPicture* pictureToClient = NULL;
+ TInt status = KErrNone;
+
+
+ if (!aPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), picture is not valid")))
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+ else if (!aPicture->iData.iRawData)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), picture raw data is not valid")))
+ iObserver.MtroFatalError(KErrAlreadyExists);
+ return;
+ }
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ // if (BuffManCI) { nothing to do, possibly send next picture for encoder, if available }
+ // Put returned picture to the iTranscoderPictureQueue
+ if (!iOptimizedDataTransfer)
+ {
+ iTranscoderPictureQueue.AddLast(*aPicture);
+
+ // There could be some decoded pictures waiting for processing, check it
+ this->MtrdvcoNewBuffers();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), Nothing to do here, since optimized data transfer in use")))
+ return;
+ }
+
+ if ( !iEncoderPictureQueue.IsEmpty() )
+ {
+ // If there are pictures available in EncoderPicture for processing, initiate data transfer from here
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), some pictures were not processed in iEncoderPictureQueue")))
+ TRAP(status, this->RunL());
+
+ if (status != KErrNone)
+ {
+ // Indicate eror status to the client
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), error[%d]"), status))
+ iObserver.MtroFatalError(status);
+ return;
+ }
+ }
+ }
+ break;
+
+ case EDecoding:
+ {
+ // Should not happen
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), Encoder returns picture in Decoding mode")))
+ TRASSERT(0);
+ }
+
+ break;
+
+ case EEncoding:
+ {
+ // Put picture to transcoder queue
+ iTranscoderPictureQueue.AddLast(*aPicture);
+
+ if (iInputPictureSize == iOutputPictureSize)
+ {
+ // Find TRPicture container corresponding to picture data & return it to the client;
+ if ( !iTranscoderTRPictureQueue.IsEmpty() )
+ {
+ pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+
+ if (pictureToClient->iRawData == aPicture->iData.iRawData)
+ {
+ // Return picture
+ iPictureSink->MtroPictureFromTranscoder(pictureToClient);
+ }
+ else
+ {
+ TPtr8 tmp(*pictureToClient->iRawData);
+ iTranscoderTRPictureQueue.AddLast(*pictureToClient);
+
+ // Encoder returns pictures in different order than they were sent
+ // Check next picture
+ pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+
+ while (*pictureToClient->iRawData != tmp)
+ {
+ if ( pictureToClient->iRawData == aPicture->iData.iRawData )
+ {
+ // Return picture
+ iPictureSink->MtroPictureFromTranscoder(pictureToClient);
+ return;
+ }
+ else
+ {
+ // Put back to the queue this picture and check the next one
+ iTranscoderTRPictureQueue.AddLast(*pictureToClient);
+ pictureToClient = iTranscoderTRPictureQueue.First();
+ pictureToClient->iLink.Deque();
+ }
+ }
+
+ // The picture has already been removed from the TR picture queue.
+ // Probably the client thought a frame was skipped and sent a new picture for encoding,
+ // therefore the client is not expecting us to send anything back => do nothing
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), Picture already returned, nothing to do")))
+ }
+ }
+ }
+ }
+ break;
+
+ case EResampling:
+ {
+ // Should not happen
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), Encoder returns picture in Resampling mode.")))
+ TRASSERT(0);
+ }
+ break;
+
+ default:
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncoderReturnPicture(), default case")))
+ TRASSERT(0);
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SendPictureToTranscoderL
+// Receives picture from the client
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SendPictureToTranscoderL(TTRVideoPicture* aPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), In")))
+ TVideoPicture* picture = NULL;
+ TInt status = KErrNone;
+ TBool encoderEnabled = EFalse;
+ TBool randomAccess = EFalse;
+
+ if (iState == ETRFatalError)
+ {
+ // Nothing to do
+ return;
+ }
+
+ if ( (iState != ETRRunning) && (iState != ETRPaused) &&
+ (iState != ETRStopped) && (iMode != EDecoding) )
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (!aPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Client sends invalid data")))
+ User::Leave(KErrArgument);
+ }
+ else if (!aPicture->iRawData)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Client sends invalid raw data")))
+ User::Leave(KErrArgument);
+ }
+
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), picture timestamp [%f]"), I64REAL(aPicture->iTimestamp.Int64()) ))
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ if (!iPictureSinkTemp)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Client did not set picture sink! leave")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iIntermediatePictureSize == iDecodedPictureSize)
+ {
+ // Picture path is Decoder->Client->Transcoder
+ // Decoder does not generate new picture until this one have not been returned
+ // Act according global settings defined in NewPicture
+ encoderEnabled = iCurrentEncoderEnabled;
+ randomAccess = iCurrentRandomAccess;
+
+ // Reset it here
+ iCurrentRandomAccess = EFalse;
+ }
+ else
+ {
+ // Picture was processed asynchronously
+ // Set global async options
+ encoderEnabled = iCurrentAsyncEncoderEnabled;
+ randomAccess = iCurrentAsyncRandomAccess;
+
+ // Reset it here
+ iCurrentAsyncRandomAccess = EFalse;
+ }
+
+ if (!encoderEnabled)
+ {
+ // Put TRPicture container to the queue in any case
+ iTranscoderTRPictureQueue.AddLast(*aPicture);
+
+ // Nothing to do for this picture, return it to decoder
+ if (iIntermediatePictureSize == iDecodedPictureSize)
+ {
+ if (iDecodedPicture)
+ {
+ // Return & reset
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), return picture [%f] to decoder"), I64REAL(iDecodedPicture->iTimestamp.Int64()) ))
+ TVideoPicture* decodedPicture = iDecodedPicture;
+ iDecodedPicture = NULL;
+ iVideoDecoderClient->ReturnPicture(decodedPicture);
+ }
+ }
+ else
+ {
+ // If picture was sent to the client asynchronously, nothing to return to decoder
+ // Picture path is Decoder->Transcoder->client->Transcoder
+ // Picture was taken from iTranscoderPictureQueue, put it back, since it's not encoded
+ // Take container for TVideoPicture
+ if ( !iContainerWaitQueue.IsEmpty() )
+ {
+ // Take container
+ picture = iContainerWaitQueue.First();
+ picture->iLink.Deque();
+ picture->iData.iRawData = aPicture->iRawData;
+ picture->iData.iDataSize = aPicture->iDataSize;
+ picture->iTimestamp = aPicture->iTimestamp;
+
+ if (!iOptimizedDataTransfer)
+ {
+ iTranscoderPictureQueue.AddLast(*picture);
+ }
+ else
+ {
+ iCIPictureBuffersQueue.AddLast(*picture);
+
+ // Some pictures were not processed yet and wait for processing
+ this->MtrdvcoNewBuffers();
+ }
+ }
+ }
+
+ return;
+ }
+
+
+ // Client returns processed picture. (Resample, if needed) and send it to encoder;
+ if ( /*iPictureSink &&*/ (iIntermediatePictureSize == iDecodedPictureSize) )
+ {
+ // Check input picture size
+ if ( aPicture->iDataSize != iDecodedPictureSize )
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), The client sets wrong picture size")))
+ User::Leave(KErrArgument);
+ }
+
+ // AA Tuning..(Codecs AOs can be higher priority, so if there are any pictures in iEncoderPictureQueue waiting for processing, send those first)
+ if ( (iDecodedPictureSize == iOutputPictureSize) && (!iEncoderPictureQueue.IsEmpty()) )
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), some pictures were not processed in iEncoderPictureQueue")))
+ this->RunL();
+ }
+
+ if (iOptimizedDataTransfer)
+ {
+ if ( !iCIPictureBuffersQueue.IsEmpty() )
+ {
+ // Target video picture buffer is already available, use it
+ picture = iCIPictureBuffersQueue.First();
+ picture->iLink.Deque();
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), picture is already available")))
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), picture not available, request new;")))
+ // Picture was already returned with WritePictureL
+ TRAP( status, picture = iVideoEncoderClient->GetTargetVideoPictureL() );
+ }
+
+ if (status != KErrNone)
+ {
+ // return decoded picture to decoder
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), GetTargetVideoPictureL leved with [%d]"), status))
+
+ if (iDecodedPicture)
+ {
+ // Return & reset
+ TVideoPicture* decodedPicture = iDecodedPicture;
+ iDecodedPicture = NULL;
+ iVideoDecoderClient->ReturnPicture(decodedPicture);
+ }
+
+ // Report the error to the client
+ iObserver.MtroFatalError(status);
+ return;
+ }
+ else if (picture)
+ {
+ // Set options for picture
+ picture->iData.iDataSize = iOutputPictureSize;
+
+ // we don't support resampling for 422, set default for 420 length
+ // Add check of output data format (422 or 420) in the future and set dataLength properly
+ TInt length = iOutputPictureSize.iWidth * iOutputPictureSize.iHeight * 3 / 2;
+
+ if ( length > picture->iData.iRawData->MaxLength() )
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), length exceeds CI buffer maxlength[%d, %d]"), length, picture->iData.iRawData->MaxLength() ))
+
+ if (iDecodedPicture)
+ {
+ // Return & reset
+ TVideoPicture* decodedPicture = iDecodedPicture;
+ iDecodedPicture = NULL;
+ iVideoDecoderClient->ReturnPicture(decodedPicture);
+ }
+
+ iObserver.MtroFatalError(KErrGeneral);
+ return;
+ }
+
+ // set length
+ picture->iData.iRawData->SetLength(length);
+ }
+ else
+ {
+ if (iRealTime) // (picture is not available, act according realtime mode)
+ {
+ // Picture buffer is not available from encoder hwdevice
+ // return decoded picture back, otherwise suspend decoding..
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Picture buffer is not available through CI, Drop") ))
+
+ if (iDecodedPicture)
+ {
+ iVideoDecoderClient->ReturnPicture(iDecodedPicture);
+ }
+
+ return;
+ }
+ else
+ {
+ // Keep picture and does not return it to DecoderClient before processing
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Picture buffer is not available through CI, store") ))
+ iWaitPictureFromClient = aPicture;
+ return;
+ }
+ }
+ }
+ else
+ {
+ if ( !iTranscoderPictureQueue.IsEmpty() )
+ {
+ picture = iTranscoderPictureQueue.First();
+ }
+ else
+ {
+ // AA (don't report FatalError & wait for newBuffers callback from the encoder)
+ // return decoded picture to decoder
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), iTranscoderPictureQueue is empty")))
+
+ if (iRealTime) // (picture is not available, act according realtime mode)
+ {
+ // Picture buffer is not available from encoder hwdevice
+ // return decoded picture back, otherwise suspend decoding..
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Picture buffer is not available FromEncoder, Drop") ))
+
+ if (iDecodedPicture)
+ {
+ iVideoDecoderClient->ReturnPicture(iDecodedPicture);
+ }
+
+ return;
+ }
+ else
+ {
+ // Keep picture and does not return it to DecoderClient before processing
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Picture buffer is not available FromEncoder, store") ))
+ iWaitPictureFromClient = aPicture;
+ return;
+ }
+ }
+ }
+
+ if (picture)
+ {
+ // Returned picture was not resampled. Resample it first.
+ TRAP(status, iScaler->SetScalerOptionsL( *(aPicture->iRawData),
+ *(picture->iData.iRawData),
+ aPicture->iDataSize,
+ picture->iData.iDataSize ) );
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Set scaler options failed[%d]"), status))
+
+ if (iDecodedPicture)
+ {
+ // Return & reset
+ TVideoPicture* decodedPicture = iDecodedPicture;
+ iDecodedPicture = NULL;
+ iVideoDecoderClient->ReturnPicture(decodedPicture);
+ }
+
+ iTranscoderTRPictureQueue.AddLast(*aPicture);
+
+ // Inform the client with an error
+ User::Leave(status);
+ }
+
+ if ( !iOptimizedDataTransfer )
+ {
+ // Remove picture from transcoder queue
+ picture->iLink.Deque();
+ }
+
+ // Scale picture
+ iScaler->Scale();
+
+ // Set params
+ picture->iTimestamp = aPicture->iTimestamp;
+ }
+ }
+ else
+ {
+ // Send picture to encoder without resampling
+ // Take container for TVideoPicture
+ if ( !iContainerWaitQueue.IsEmpty() )
+ {
+ // Take container
+ picture = iContainerWaitQueue.First();
+ picture->iLink.Deque();
+ picture->iData.iRawData = aPicture->iRawData;
+ picture->iData.iDataSize = aPicture->iDataSize;
+ picture->iTimestamp = aPicture->iTimestamp;
+ }
+ }
+
+ // Put client's container to TRPicture queue
+ iTranscoderTRPictureQueue.AddLast(*aPicture);
+
+ if (picture)
+ {
+ // Encode picture
+ if (randomAccess)
+ {
+ iVideoEncoderClient->SetRandomAccessPoint();
+ }
+
+ iVideoEncoderClient->EncodePictureL(picture);
+ }
+
+ // AA
+ // return decoded picture here, if there's some available
+ if (iDecodedPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Return decoded picture now")))
+
+ // Return & reset
+ TVideoPicture* decodedPicture = iDecodedPicture;
+ iDecodedPicture = NULL;
+ iVideoDecoderClient->ReturnPicture(decodedPicture);
+ }
+ }
+ break;
+
+ case EDecoding:
+ {
+ // Client returns decoded picture back.
+ if (iDecodedPictureSize == iOutputPictureSize)
+ {
+ if (iDecodedPicture)
+ {
+ iVideoDecoderClient->ReturnPicture(iDecodedPicture);
+ }
+ }
+ else
+ {
+ // Put picture back to the queue
+ iTranscoderPictureQueue.AddLast(*iVideoPictureTemp);
+ }
+ }
+ break;
+
+ case EEncoding:
+ {
+ // Check input picture size
+ if ( aPicture->iDataSize != iInputPictureSize )
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Encoding: The client sets wrong picture size")))
+ User::Leave(KErrArgument);
+ }
+
+ // Client writes new picture to encode. Encode it and return back;
+ if (!iPictureSink)
+ {
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), picture sink is not set by the client")))
+ User::Leave(KErrNotReady);
+ }
+
+ if ( !iTranscoderPictureQueue.IsEmpty() )
+ {
+ picture = iTranscoderPictureQueue.First();
+
+ if (iInputPictureSize != iOutputPictureSize)
+ {
+ // Resample this picture first, since picture sizes are different
+ iScaler->SetScalerOptionsL( *(aPicture->iRawData), *(picture->iData.iRawData), aPicture->iDataSize,
+ picture->iData.iDataSize );
+
+ // Scale
+ iScaler->Scale();
+ }
+ else
+ {
+ picture->iData.iDataSize = aPicture->iDataSize;
+ picture->iData.iRawData = aPicture->iRawData;
+ }
+
+ picture->iData.iDataFormat = EYuvRawData;
+ picture->iTimestamp = aPicture->iTimestamp;
+
+ // Remove picture from transcoder queue
+ picture->iLink.Deque();
+
+ // Put video picture to encoder queue
+ iEncoderPictureQueue.AddLast(*picture);
+
+ // Make request to process this picture
+ this->DoRequest();
+
+ if (iInputPictureSize != iOutputPictureSize)
+ {
+ // Return picture to the client
+ iPictureSink->MtroPictureFromTranscoder(aPicture);
+ }
+ // Add picture to TR queue unless it's already there
+ else if ( iTranscoderTRPictureQueue.IsEmpty() ||
+ ((iTranscoderTRPictureQueue.First() != aPicture) &&
+ (iTranscoderTRPictureQueue.Last() != aPicture)) )
+ {
+ // Keep aPicture until picture is returned by the encoder
+ iTranscoderTRPictureQueue.AddLast(*aPicture);
+ }
+ }
+ }
+ break;
+
+ case EResampling:
+ {
+ User::Leave(KErrInUse);
+ }
+ break;
+
+ case EOperationNone:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+
+ default:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+ }
+
+ PRINT((_L("CTRTranscoderImp::SendPictureToTranscoderL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoNewBuffer
+// New buffer from the Video encoder is available
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoNewBuffer(CCMRMediaBuffer* aBuffer)
+ {
+ if (!aBuffer)
+ {
+ // Should never happend
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffer(), EncoderClient sends invalid data, panic")))
+ TRASSERT(0);
+ }
+
+ if (!iMediaSink)
+ {
+ // Should never happend at this point
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffer(), invalid media sink, panic")))
+ TRASSERT(0);
+ }
+
+ TRAPD(status, iMediaSink->WriteBufferL(aBuffer));
+ if (status != KErrNone)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffer(), WriteBufferL status[%d]"), status))
+ iObserver.MtroFatalError(status);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::ResampleL
+// Resamples video picture to new resolution
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::ResampleL(TPtr8& aSrc, TPtr8& aTrg)
+ {
+ PRINT((_L("CTRTranscoderImp::ResampleL(), In")))
+
+ if ( (iState != ETRInitialized) && (iState != ETRRunning) )
+ {
+ PRINT((_L("CTRTranscoderImp::ResampleL(), called in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iMode != EResampling)
+ {
+ PRINT((_L("CTRTranscoderImp::ResampleL(), supported only in Resampling mode")))
+ User::Leave(KErrInUse);
+ }
+
+ if (iScaler)
+ {
+ // SetScaler options
+ iScaler->SetScalerOptionsL(aSrc, aTrg, iInputPictureSize, iOutputPictureSize);
+ iScaler->Scale();
+ }
+ else
+ {
+ PRINT((_L("CTRTranscoderImp::ResampleL(), scaler is not valid")))
+ TRASSERT(0);
+ }
+
+ PRINT((_L("CTRTranscoderImp::ResampleL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::StopL
+// Stops data processing synchronously
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::StopL()
+ {
+ PRINT((_L("CTRTranscoderImp::StopL(), In")))
+
+
+ if ( (iState != ETRRunning) && (iState != ETRPaused) && (iState != ETRFatalError) )
+ {
+ PRINT((_L("CTRTranscoderImp::StopL(), wrong state, leave")))
+ User::Leave(KErrNotReady);
+ }
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ // Discard all frames waiting to be sent to encoder
+ iEncoderPictureQueue.Reset();
+
+ iVideoDecoderClient->StopL();
+ iVideoEncoderClient->StopL();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EDecoding:
+ {
+ iVideoDecoderClient->StopL();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EEncoding:
+ {
+ iVideoEncoderClient->StopL();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EResampling:
+ {
+ iState = ETRStopped;
+ }
+ break;
+
+ case EOperationNone:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+
+ PRINT((_L("CTRTranscoderImp::StopL(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::AsyncStopL
+// Stops data processing asynchronously
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::AsyncStopL()
+ {
+ PRINT((_L("CTRTranscoderImp::AsyncStopL(), Async In")))
+
+
+ if (iState != ETRRunning)
+ {
+ PRINT((_L("CTRTranscoderImp::AsyncStopL() Async, wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ iAsyncStop = ETrue;
+ iVideoDecoderClient->AsyncStopL();
+ }
+ break;
+
+ case EDecoding:
+ {
+ iEncoderStreamEnd = ETrue;
+ iVideoDecoderClient->AsyncStopL();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EEncoding:
+ {
+ iDecoderStreamEnd = ETrue;
+ iVideoEncoderClient->AsyncStopL();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EResampling:
+ {
+ // Just complete asyncStop right here
+ iObserver.MtroAsyncStopComplete();
+ iState = ETRStopped;
+ }
+ break;
+
+ case EOperationNone:
+ {
+ User::Leave(KErrNotReady);
+ }
+ break;
+
+ default:
+ {
+ User::Leave(KErrNotReady);
+ }
+ }
+
+
+ PRINT((_L("CTRTranscoderImp::AsyncStopL(), Async Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoEncStreamEnd
+// Informs that last data was processed by encoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoEncStreamEnd()
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncStreamEnd()")))
+ iEncoderStreamEnd = ETrue;
+
+ if (iDecoderStreamEnd)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoEncStreamEnd(), MtroAsyncStopComplete")))
+ iObserver.MtroAsyncStopComplete();
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::DecoderStreamEnd
+// Informs that last data was processed by decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoDecStreamEnd()
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecStreamEnd()")))
+ TInt status = KErrNone;
+ iDecoderStreamEnd = ETrue;
+
+ if (iEncoderStreamEnd)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecStreamEnd(), MtroAsyncStopComplete")))
+ iObserver.MtroAsyncStopComplete();
+ return;
+ }
+
+ if (iAsyncStop)
+ {
+ // Call now asyncStop for encoder
+ TRAP(status, iVideoEncoderClient->AsyncStopL());
+
+ if (status != KErrNone)
+ {
+ // Report error to the client during stop
+ PRINT((_L("CTRTranscoderImp::MtrdvcoDecStreamEnd(), EncAsyncStop status[%d]"), status))
+ iObserver.MtroFatalError(status);
+ }
+
+ iState = ETRStopped;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoRendererReturnPicture
+// Receives picture from renderer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoRendererReturnPicture(TVideoPicture* /*aPicture*/)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoFatalError
+// Reports the fatal error to the client
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoFatalError(TInt aError)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoFatalError(), error[%d]"), aError))
+ iFatalError = aError;
+ iState = ETRFatalError;
+ iObserver.MtroFatalError(aError);
+ }
+
+
+// AA (PV requires to use that, otherwise depends on the decoder hwdevice & decoder itself)
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetDecoderInitDataL
+// Sends init data for decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetDecoderInitDataL(TPtrC8& /*aInitData*/)
+ {
+ // Remove this API in the future;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetCodingStandardSpecificInitOutputLC
+// Retrieve coding options from encoder client
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CTRTranscoderImp::GetCodingStandardSpecificInitOutputLC()
+ {
+ if ( iState != ETRInitialized )
+ {
+ PRINT((_L("CTRTranscoderImp::GetCodingStandardSpecificInitOutputLC(), wrong state, leave")))
+ User::Leave(KErrNotReady);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ return iVideoEncoderClient->GetCodingStandardSpecificInitOutputLC();
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::EnablePictureSink
+// Enable / Disable picture sink
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::EnablePictureSink(TBool aEnable)
+ {
+ if (iMode != EFullTranscoding)
+ {
+ // nothing to do in other mode
+ PRINT((_L("CTRTranscoderImp::EnablePictureSink(), nothing to do, wrong mode")))
+ return;
+ }
+
+ if (iPictureSinkClientSetting != aEnable)
+ {
+ // Setting was changed
+ iPictureSinkSettingChanged = ETrue;
+ PRINT((_L("CTRTranscoderImp::EnablePictureSink(), EnablePictureSink setting changed[%d]"), aEnable))
+ }
+
+ iPictureSinkClientSetting = aEnable;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::EnableEncoder
+// Enable / Disable encoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::EnableEncoder(TBool aEnable)
+ {
+ if (iMode != EFullTranscoding)
+ {
+ // nothing to do in other mode
+ PRINT((_L("CTRTranscoderImp::EnableEncoder(), nothing to do, wrong mode")))
+ return;
+ }
+
+ if (iEncoderEnableClientSetting != aEnable)
+ {
+ // Setting was changed
+ iEncoderEnabledSettingChanged = ETrue;
+ PRINT((_L("CTRTranscoderImp::EnableEncoder(), EnableEncoder setting changed[%d]"), aEnable))
+ }
+
+ iEncoderEnableClientSetting = aEnable;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::SetRandomAccessPoint
+// Sets random access
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::SetRandomAccessPoint()
+ {
+ if (iMode != EFullTranscoding)
+ {
+ // nothing to do in other mode
+ PRINT((_L("CTRTranscoderImp::EnableEncoder(), nothing to do, wrong mode")))
+ return;
+ }
+
+ iSetRandomAccessPoint = ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::MtrdvcoNewBuffers
+// New buffers from encoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoNewBuffers()
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffers()")))
+ TInt status = KErrNone;
+ TTRVideoPicture* pictureFromClient = NULL;
+ TVideoPicture* newDecodedPicture = NULL;
+
+
+ if (iRealTime)
+ {
+ // Should never be called in normal data flow or realTime mode, ignore this call!
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffers(), return immediately")))
+ return;
+ }
+
+ // Use this call to initiate data transfer if there are available decoded picture waiting for processing
+ if (iWaitPictureFromClient)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffers(), iWaitPictureFromClient, [0x%x], call SendPictureToTranscoderL()"), iWaitPictureFromClient))
+
+ // Simulate call from the client since picture was not processed
+ pictureFromClient = iWaitPictureFromClient;
+
+ // Reset picture, it can be reinitialized in the following call
+ iWaitPictureFromClient = NULL;
+
+ TRAP( status, this->SendPictureToTranscoderL(pictureFromClient) );
+
+ if (status != KErrNone)
+ {
+ // Report error to the client
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffers(), status[%d]"), status))
+ iObserver.MtroFatalError(status);
+ }
+
+ return;
+ }
+
+ if (iWaitNewDecodedPicture)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoNewBuffers(), iWaitNewDecodedPicture[0x%x]"), iWaitNewDecodedPicture))
+ newDecodedPicture = iWaitNewDecodedPicture;
+
+ // Reset newdecoded picture
+ iWaitNewDecodedPicture = NULL;
+
+ // Simulate new decoded picture call
+ this->MtrdvcoNewPicture(newDecodedPicture);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::EstimateTranscodeTimeFactorL
+// Returns a time estimate of how long it takes to process one second of the input video
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TReal CTRTranscoderImp::EstimateTranscodeTimeFactorL(const TTRVideoFormat& aInput, const TTRVideoFormat& aOutput)
+ {
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), In")))
+
+ if ( iState == ETRNone )
+ {
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), Transcoder is in wrong state")))
+ User::Leave(KErrNotReady);
+ }
+
+ // Get frame rate for output / input video
+ TReal time = 0.0;
+ TReal encodeFrameRate = GetFrameRateL();
+ TReal decodeFrameRate = 0.0;
+ iObserver.MtroSetInputFrameRate(decodeFrameRate);
+
+ // Use default frames rates if not set
+ if (encodeFrameRate == 0.0) encodeFrameRate = KTRDefaultSrcRate;
+ if (decodeFrameRate == 0.0) decodeFrameRate = KTRDefaultSrcRate;
+
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), encode frame rate: %.2f"), encodeFrameRate))
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), decode frame rate: %.2f"), decodeFrameRate))
+
+ switch(iMode)
+ {
+ case EFullTranscoding:
+ {
+ // Estimate the time for decoding, encoding and possible resampling
+ time += iVideoEncoderClient->EstimateEncodeFrameTimeL(aOutput, iOutputCodec) * encodeFrameRate;
+ time += iVideoDecoderClient->EstimateDecodeFrameTimeL(aInput, iInputCodec) * decodeFrameRate;
+ time += iScaler->EstimateResampleFrameTime(aInput, aOutput) * decodeFrameRate;
+
+ break;
+ }
+
+ case EDecoding:
+ {
+ // Estimate the time for decoding and possible resampling
+ time += iVideoDecoderClient->EstimateDecodeFrameTimeL(aInput, iInputCodec) * decodeFrameRate;
+ time += iScaler->EstimateResampleFrameTime(aInput, aOutput) * decodeFrameRate;
+
+ break;
+ }
+
+ case EEncoding:
+ {
+ // Estimate the time for encoding and possible resampling
+ time += iVideoEncoderClient->EstimateEncodeFrameTimeL(aOutput, iOutputCodec) * encodeFrameRate;
+ time += iScaler->EstimateResampleFrameTime(aInput, aOutput) * encodeFrameRate;
+
+ break;
+ }
+
+ case EResampling:
+ {
+ // Estimate the time for resampling
+ time += iScaler->EstimateResampleFrameTime(aInput, aOutput) * decodeFrameRate;
+
+ break;
+ }
+
+ default:
+ {
+ // Transcoder is not ready
+ User::Leave(KErrNotReady);
+ break;
+ }
+ }
+
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), time factor: %.2f"), time))
+
+ PRINT((_L("CTRTranscoderImp::EstimateTranscodeTimeFactorL(), Out")))
+
+ return time;
+ }
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::GetMaxFramesInProcessing
+// Get max number of frames in processing
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CTRTranscoderImp::GetMaxFramesInProcessing()
+ {
+ return iMaxFramesInProcessing;
+ }
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::EnablePausing
+// Enable / Disable pausing of transcoding if resources are lost
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::EnablePausing(TBool aEnable)
+ {
+ if (iVideoDecoderClient)
+ {
+ iVideoDecoderClient->EnableResourceObserver(aEnable);
+ }
+
+ if (iVideoEncoderClient)
+ {
+ iVideoEncoderClient->EnableResourceObserver(aEnable);
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::::MmvroResourcesLost
+// Indicates that a media device has lost its resources
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoResourcesLost(TBool aFromDecoder)
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoResourcesLost(), In")))
+
+ if ( (iState == ETRRunning) || (iState == ETRInitialized) || (iState == ETRStopped) )
+ {
+ iVideoDecoderClient->Pause();
+ iState = ETRPaused;
+
+ iDecoderResourceLost = aFromDecoder;
+
+ if (!aFromDecoder)
+ iVideoEncoderClient->Pause();
+
+ // Return decoded picture
+ if (iWaitNewDecodedPicture)
+ {
+ iVideoDecoderClient->ReturnPicture(iWaitNewDecodedPicture);
+ iWaitNewDecodedPicture = NULL;
+ }
+
+ iObserver.MtroSuspend();
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoResourcesLost(), Out")))
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTRTranscoderImp::::MmvroResourcesRestored
+// Indicates that a media device has regained its resources
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTRTranscoderImp::MtrdvcoResourcesRestored()
+ {
+ PRINT((_L("CTRTranscoderImp::MtrdvcoResourcesRestored(), In")))
+
+ if ( (iState == ETRPaused) || (iState == ETRInitialized) || (iState == ETRStopped) )
+ {
+ // Clear all events
+ if( iNewEvent )
+ {
+ iNewEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iNewEvent);
+ iNewEvent = NULL;
+ }
+
+ while( !iTranscoderEventQueue.IsEmpty() )
+ {
+ // Get new event
+ iNewEvent = iTranscoderEventQueue.First();
+ iNewEvent->iLink.Deque();
+
+ iNewEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iNewEvent);
+ iNewEvent = NULL;
+ }
+
+ if( iAsyncEvent )
+ {
+ iAsyncEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iAsyncEvent);
+ iAsyncEvent = NULL;
+ }
+
+ while( !iTranscoderAsyncEventQueue.IsEmpty() )
+ {
+ // Get new event
+ iAsyncEvent = iTranscoderAsyncEventQueue.First();
+ iAsyncEvent->iLink.Deque();
+
+ iAsyncEvent->Reset();
+ iTranscoderEventSrc.AddLast(*iAsyncEvent);
+ iAsyncEvent = NULL;
+ }
+
+ // Force update of PS / EE settings
+ iPictureSinkSettingChanged = ETrue;
+ iEncoderEnabledSettingChanged = ETrue;
+
+ TRAPD( error, iVideoDecoderClient->ResumeL() );
+ if( error != KErrNone ) { }
+
+ if (!iDecoderResourceLost)
+ {
+ iVideoEncoderClient->Resume();
+ }
+
+ iState = ETRRunning;
+
+ iObserver.MtroResume();
+ }
+
+ PRINT((_L("CTRTranscoderImp::MtrdvcoResourcesRestored(), Out")))
+ }
+
+// End of file