/*
* 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