diff -r 000000000000 -r 951a5db380a0 videoeditorengine/vedtranscoder/src/Ctrvideodecoderclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/vedtranscoder/src/Ctrvideodecoderclient.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1468 @@ +/* +* 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: +* Video decoder client. +* +*/ + + + +// INCLUDE FILES +#include +#include "ctrvideodecoderclient.h" +#include "ctrtranscoder.h" +#include "ctrdevvideoclientobserver.h" +#include "ctrsettings.h" +#include "ctrhwsettings.h" + + +// MACROS +#define TRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CTRANSCODERVIDEODECODERCLIENT"), -10010)) + + +// CONSTANTS + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CTRVideoDecoderClient* CTRVideoDecoderClient::NewL(MTRDevVideoClientObserver& aObserver) + { + PRINT((_L("CTRVideoDecoderClient::NewL(), In"))) + CTRVideoDecoderClient* self = new (ELeave) CTRVideoDecoderClient(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + + PRINT((_L("CTRVideoDecoderClient::NewL(), Out"))) + return self; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::CTRVideoDecoderClient +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CTRVideoDecoderClient::CTRVideoDecoderClient(MTRDevVideoClientObserver& aObserver) : + iObserver(aObserver) + { + iDevVideoPlay = NULL; + iCompresedFormat = NULL; + iUid = TUid::Null(); + iFallbackUid = TUid::Null(); + iHwDeviceId = THwDeviceId(0); + iInputBuffer = NULL; + iCodedBuffer = NULL; + iDecodedPicture = NULL; + + iVideoResourceHandlerCI = NULL; + + iFatalError = KErrNone; + iDataUnitType = EDuCodedPicture; + iStop = EFalse; + iLastTimestamp = -1; + iAcceleratedCodecSelected = EFalse; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::ConstructL() + { + iDevVideoPlay = CMMFDevVideoPlay::NewL(*this); + } + + +// --------------------------------------------------------- +// CTRVideoDecoderClient::~CTRVideoDecoderClient() +// Destructor +// --------------------------------------------------------- +// +CTRVideoDecoderClient::~CTRVideoDecoderClient() + { + PRINT((_L("CTRVideoDecoderClient::~CTRVideoDecoderClient(), In"))) + + if (iDevVideoPlay) + { + delete iDevVideoPlay; + iDevVideoPlay = NULL; + } + + iInputBuffer = NULL; + + if (iCompresedFormat) + { + delete iCompresedFormat; + } + + PRINT((_L("CTRVideoDecoderClient::~CTRVideoDecoderClient(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::SupportsCodec +// Checks whether this coded is supported +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CTRVideoDecoderClient::SupportsCodec(const TDesC8& aFormat, const TDesC8& aShortFormat, TInt aUid, TInt aFallbackUid) + { + TBool supports = EFalse; + TBool preferredFound = EFalse; + TBool fallbackFound = EFalse; + + if (iDevVideoPlay) + { + RArray decoders; + + TRAPD( status, iDevVideoPlay->FindDecodersL(aShortFormat, 0/*aPreProcType*/, decoders, EFalse/*aExactMatch*/) ); + + if( status != KErrNone ) + { + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), status[%d]"), status)) + supports = EFalse; + } + else if( decoders.Count() <= 0 ) + { + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), No decoders found"))) + supports = EFalse; + } + else + { + + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), %d decoders found"), decoders.Count() )) + + // Check if any of the found decoders matches with the given Uids + for( TInt i = 0; i < decoders.Count(); ++i ) + { + + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), found codec 0x%x"), decoders[i].iUid)) + + if( decoders[i].iUid == aUid ) + { + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), preferred found"))) + iUid = decoders[i]; + preferredFound = ETrue; + } + if( decoders[i].iUid == aFallbackUid ) + { + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), fallback found"))) + iFallbackUid = decoders[i]; + fallbackFound = ETrue; + } + + if( preferredFound && fallbackFound ) + { + // No need to search anymore + break; + } + } + } + + decoders.Reset(); + decoders.Close(); + } + + if( !preferredFound ) + { + // Preferred decoder was not found => Probably the given decoder Uid is wrong + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), No supported decoders found"))) + supports = EFalse; + } + else + { + PRINT((_L("CTRVideoDecoderClient::SupportsCodec(), Supported decoder found: 0x%x"), iUid.iUid)) + iMimeType = aFormat; + iShortMimeType = aShortFormat; + supports = ETrue; + } + + return supports; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::SetCodecParametersL +// Sets codec parameters +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::SetCodecParametersL(TInt aCodecType, TInt aCodecLevel, const TTRVideoFormat& aInputFormat, + const TTRVideoFormat& aOutputFormat) + { + PRINT((_L("CTRVideoDecoderClient::SetCodecParametersL(), In"))) + TInt status = KErrNone; + iCodecType = aCodecType; + iCodecLevel = aCodecLevel; + iInputFormat = aInputFormat; + iOutputFormat = aOutputFormat; + + // Input format + if (!iCompresedFormat) + { + iCompresedFormat = CCompressedVideoFormat::NewL( iMimeType ); + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + + if (status != KErrNone) + { + // Try again with the fallback decoder if one exists + if( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iFallbackUid) ); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::SetCodecParametersL(), Failed to get codec info"))) + User::Leave(KErrNotSupported); + } + + PRINT((_L("CTRVideoDecoderClient::SetCodecParametersL(), Reverting to fallback decoder"))) + + // Fallback ok, take it + iUid = iFallbackUid; + } + else + { + PRINT((_L("CTRVideoDecoderClient::SetCodecParametersL(), No suitable decoders found"))) + User::Leave(KErrNotSupported); + } + } + + PRINT((_L("CTRVideoDecoderClient::SetCodecParametersL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::CheckCodecInfoL +// Checks coded info +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CTRVideoDecoderClient::CheckCodecInfoL(TUid aUid) + { + CVideoDecoderInfo* decoderInfo = NULL; // Decoder info for retrieving capabilities + TInt status = KErrNone; + TBool accelerated = EFalse; + + + // Check decoder + PRINT((_L("CTRVideoDecoderClient::CheckCodecInfoL(), getting info from [0x%x]"), aUid.iUid )) + decoderInfo = iDevVideoPlay->VideoDecoderInfoLC( aUid ); + + if (!decoderInfo) + { + PRINT((_L("CTRVideoDecoderClient::CheckCodecInfoL(), getting info from [0x%x] failed[%d]"), aUid.iUid, status )) + User::Leave(KErrNotSupported); + } // AA skip info check before symbian fix + else /* if ( !decoderInfo->SupportsFormat(*iCompresedFormat) ) // Check input format + { + PRINT((_L("CTRVideoDecoderClient::CheckCodecInfoL(), Input format is not supported"))) + status = KErrNotSupported; + } + else */ + { + // Check max rate for requested image format + TSize maxSize = decoderInfo->MaxPictureSize(); + + if ( (iInputFormat.iSize.iWidth > maxSize.iWidth) || (iInputFormat.iSize.iHeight > maxSize.iHeight) ) + { + PRINT((_L("CTRVideoDecoderClient::CheckCodecInfoL(), Picture size is not supported"))) + status = KErrNotSupported; + } + } + + accelerated = decoderInfo->Accelerated(); + + // Delete codec info + CleanupStack::PopAndDestroy(decoderInfo); + + if (status != KErrNone) + { + User::Leave(status); + } + + return accelerated; + } + + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::InitializeL +// Initializes encoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::InitializeL() + { + PRINT((_L("CTRVideoDecoderClient::InitializeL(), In"))) + TUint maxBufferSize = 0; + TInt status = KErrNone; + + + switch(iInputFormat.iDataType) + { + case CTRTranscoder::ETRDuCodedPicture: + { + iDataUnitType = EDuCodedPicture; + break; + } + + case CTRTranscoder::ETRDuVideoSegment: + { + iDataUnitType = EDuVideoSegment; + break; + } + + default: + { + // Should never happend. Decoder does not support uncompressed input format. + TRASSERT(0); + } + } + + iBufferOptions.iMinNumInputBuffers = KTRDecoderMinNumberOfBuffers; + + // Select decoder first + this->SelectDecoderL(); + + // Set now output format for this device + TRAP(status, iDevVideoPlay->SetOutputFormatL(iHwDeviceId, iUncompressedFormat)); + + // 3. Buffer options + iBufferOptions.iPreDecodeBufferSize = 0; // "0" - use default decoder value + iBufferOptions.iMaxPostDecodeBufferSize = 0; // No limitations + iBufferOptions.iPreDecoderBufferPeriod = 0; + iBufferOptions.iPostDecoderBufferPeriod = 0; + + // Check max coded picture size for specified codec level + switch(iCodecLevel) + { + case KTRH263CodecLevel10: + { + maxBufferSize = KTRMaxBufferSizeLevel10; + break; + } + + case KTRH263CodecLevel20: + { + maxBufferSize = KTRMaxBufferSizeLevel20; + break; + } + + case KTRH263CodecLevel30: + { + maxBufferSize = KTRMaxBufferSizeLevel30; + break; + } + + case KTRH263CodecLevel40: + { + maxBufferSize = KTRMaxBufferSizeLevel40; + break; + } + + case KTRH263CodecLevel50: + { + maxBufferSize = KTRMaxBufferSizeLevel50; + break; + } + + case KTRH263CodecLevel60: + { + maxBufferSize = KTRMaxBufferSizeLevel60; + break; + } + + case KTRH263CodecLevel70: + { + maxBufferSize = KTRMaxBufferSizeLevel70; + break; + } + + case KTRH264CodecLevel10: + { + maxBufferSize = KTRMaxBufferSizeH264Level10; + break; + } + + case KTRH264CodecLevel10b: + { + maxBufferSize = KTRMaxBufferSizeH264Level10b; + break; + } + + case KTRH264CodecLevel11: + { + maxBufferSize = KTRMaxBufferSizeH264Level11; + break; + } + + case KTRH264CodecLevel12: + { + maxBufferSize = KTRMaxBufferSizeH264Level12; + break; + } + + case KTRH264CodecLevel13: + { + maxBufferSize = KTRMaxBufferSizeH264Level13; + break; + } + + case KTRH264CodecLevel20: + { + maxBufferSize = KTRMaxBufferSizeH264Level20; + break; + } + + case KTRH264CodecLevel30: + { + maxBufferSize = KTRMaxBufferSizeH264Level30; + break; + } + + case KTRH264CodecLevel31: + { + maxBufferSize = KTRMaxBufferSizeH264Level31; + break; + } + + case KTRMPEG4CodecLevel0: + { + maxBufferSize = KTRMaxBufferSizeLevel0; + break; + } + + case KTRMPEG4CodecLevel1: + { + maxBufferSize = KTRMaxBufferSizeLevel1; + break; + } + + case KTRMPEG4CodecLevel2: + { + maxBufferSize = KTRMaxBufferSizeLevel2; + break; + } + + case KTRMPEG4CodecLevel3: + { + maxBufferSize = KTRMaxBufferSizeLevel3; + break; + } + + case KTRMPEG4CodecLevel0b: + { + maxBufferSize = KTRMaxBufferSizeLevel0b; + break; + } + + case KTRMPEG4CodecLevel4a: + { + maxBufferSize = KTRMaxBufferSizeLevel4a; + break; + } + + default: + { + maxBufferSize = KTRMaxBufferSizeLevel0; + break; + } + } + + iBufferOptions.iMaxInputBufferSize = maxBufferSize; + PRINT((_L("CTRVideoDecoderClient::InitializeL(), InputBufferSize[%d], NumberOfBuffers[%d]"), + iBufferOptions.iMaxInputBufferSize, iBufferOptions.iMinNumInputBuffers )) + + iDevVideoPlay->SetBufferOptionsL(iBufferOptions); + + if (iScalingInUse) + { + PRINT((_L("CTRVideoDecoderClient::InitializeL(), Enabling scaling"))) + if (iScalingWithDeblocking) + { + // Enable scaling with deblocking + iDevVideoPlay->SetPostProcessTypesL(iHwDeviceId, EPpScale | EPpDeblocking); + } + else + { + // Deblocking not supported, enable just scaling + iDevVideoPlay->SetPostProcessTypesL(iHwDeviceId, EPpScale); + } + + iDevVideoPlay->SetScaleOptionsL(iHwDeviceId, iScaledOutputSize, EFalse); + } + + // Initialize devVideoPlay + iDevVideoPlay->Initialize(); + + PRINT((_L("CTRVideoDecoderClient::InitializeL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::SelectDecoderL +// Selects decoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::SelectDecoderL() + { + PRINT(( _L("CTRVideoDecoderClient::SelectDecoderL(), In") )) + TInt status = KErrNone; + TBool exit = EFalse; + + TVideoDataUnitEncapsulation dataUnitEncapsulation = EDuElementaryStream; + + // Use generic payload encapsulation for H.264 + if (iCodecType == EH264) + { + dataUnitEncapsulation = EDuGenericPayload; + } + + if (iUid != TUid::Null()) + { + TRAP( status, iHwDeviceId = iDevVideoPlay->SelectDecoderL(iUid) ); + } + else + { + // Probably the error already exists, if iUid == NULL; + status = KErrAlreadyExists; + } + + while (!exit ) + { + if (status == KErrNone) + { + // To get Output format list devvideoplay requires to define output format first. + iDevVideoPlay->SetInputFormatL(iHwDeviceId, *iCompresedFormat, iDataUnitType, dataUnitEncapsulation, ETrue); + + // It's time to check input format support (since the plugin is loaded to the memory) + iUncompressedFormat.iDataFormat = EYuvRawData; + + TUncompressedVideoFormat uncFormat; + TBool found = EFalse; + TInt pattern1, pattern2; + TInt dataLayout; + + switch (iOutputFormat.iDataType) + { + case CTRTranscoder::ETRYuvRawData420: + { + pattern1 = EYuv420Chroma1; + pattern2 = EYuv420Chroma2; + dataLayout = EYuvDataPlanar; + } + break; + + case CTRTranscoder::ETRYuvRawData422: + { + pattern1 = EYuv422Chroma1; + pattern2 = EYuv422Chroma2; + dataLayout = EYuvDataInterleavedBE; + } + break; + + default: + { + // set 420 as a default + pattern1 = EYuv420Chroma1; + pattern2 = EYuv420Chroma2; + dataLayout = EYuvDataPlanar; + } + } + + RArray supportedOutputFormats; + TRAP(status, iDevVideoPlay->GetOutputFormatListL( iHwDeviceId, supportedOutputFormats )); + + TInt formatCount = 0; + if (status == KErrNone) + { + formatCount = supportedOutputFormats.Count(); + PRINT((_L("CTRVideoDecoderClient::InitializeL(), formatCount[%d]"), formatCount )) + } + + if (formatCount <= 0) + { + supportedOutputFormats.Close(); + status = KErrAlreadyExists; + PRINT((_L("CTRVideoDecoderClient::InitializeL(), There are no supported output formats") )) + //User::Leave(KErrNotSupported); + } + else + { + // Check the most important paramers + for ( TInt i = 0; i < formatCount; i ++ ) + { + uncFormat = supportedOutputFormats[i]; + PRINT((_L("CTRVideoDecoderClient::InitializeL(), pattern[%d]"), uncFormat.iYuvFormat.iPattern )) + + if ( (uncFormat.iDataFormat == iUncompressedFormat.iDataFormat) && + (uncFormat.iYuvFormat.iDataLayout == dataLayout) && + ( (uncFormat.iYuvFormat.iPattern == pattern1) || + (uncFormat.iYuvFormat.iPattern == pattern2) ) ) + { + // Assign the rest of parameters + iUncompressedFormat = uncFormat; + found = ETrue; + exit = ETrue; + supportedOutputFormats.Close(); + break; + } + } + + if (!found) + { + supportedOutputFormats.Close(); + status = KErrAlreadyExists; + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Supported format was not found") )) + //User::Leave(KErrNotSupported); + } + } + + } + else + { + if (iScalingInUse) + { + // We can't revert to fallback decoder here since scaling has been taken into use + // and we can't check here if the fallback decoder supports scaling nor + // disable scaling if it's not supported + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Failed to select decoder"))) + User::Leave(KErrNotSupported); + } + + // Try again with the fallback decoder if one exists + if( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + PRINT((_L("CTRVideoDecoderClient::SelectEncoderL(), Reverting to fallback decoder"))) + iUid = iFallbackUid; + } + else + { + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Failed to select decoder"))) + User::Leave(KErrNotSupported); + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Failed to get codec info"))) + User::Leave(KErrNotSupported); + } + + TRAP(status, iHwDeviceId = iDevVideoPlay->SelectDecoderL(iUid)); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Failed to select decoder"))) + User::Leave(KErrNotSupported); + } + } + } + + PRINT((_L("CTRVideoDecoderClient::SelectDecoderL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoInitComplete +// Notifies for initialization complete with init status +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoInitComplete(TInt aError) + { + if ((aError == KErrHardwareNotAvailable) || (aError == KErrNotSupported)) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoInitComplete(), Error in initialization"))) + + // Map both error codes to the same + aError = KErrNotSupported; + + // Try again with the fallback decoder if one exists + while( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoInitComplete(), Reverting to fallback decoder"))) + + iUid = iFallbackUid; + + // Devvideo must be recreated from scratch + if (iDevVideoPlay) + { + delete iDevVideoPlay; + iDevVideoPlay = NULL; + } + + TRAPD( status, iDevVideoPlay = CMMFDevVideoPlay::NewL(*this) ); + if (status != KErrNone) + { + // Something went wrong, let CTRTranscoderImp handle the error + PRINT((_L("CTRVideoDecoderClient::MdvpoInitComplete(), Failed to create DevVideoPlay"))) + break; + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + if (status != KErrNone) + { + // Fallback decoder can not be used, let CTRTranscoderImp handle the error + PRINT((_L("CTRVideoDecoderClient::MdvpoInitComplete(), Failed to get codec info"))) + break; + } + + // We are now ready to reinitialize the decoder, let CTRTranscoderImp do it + aError = KErrHardwareNotAvailable; + break; + } + } + + iObserver.MtrdvcoDecInitializeComplete(aError); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::StartL +// Starts decoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::StartL() + { + PRINT((_L("CTRVideoDecoderClient::StartL(), In"))) + + // Start decoding + if (iFatalError == KErrNone) + { + iDevVideoPlay->Start(); + } + + if (!iInputBuffer) + { + // Get buffer from the decoder to fill + iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize); + } + + // Reset iStop + iStop = EFalse; + iPause = EFalse; + + // Reset ts monitor + iLastTimestamp = -1; + + PRINT((_L("CTRVideoDecoderClient::StartL(), Out"))) + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::Pause +// Pauses decoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::Pause() + { + PRINT((_L("CTRVideoDecoderClient::Pause(), In"))) + + // Pause decoding + iDevVideoPlay->Pause(); + + // Return coded buffer to client since it can not be send to decoder now + if (iCodedBuffer) + { + CCMRMediaBuffer* codedBuffer = iCodedBuffer; + + // Reset buffer ptr + iCodedBuffer = NULL; + + iObserver.MtrdvcoReturnCodedBuffer(codedBuffer); + } + + // Get all pictures from devvideoplay and return them to decoder + TVideoPicture* picture = NULL; + TRAPD(status, picture = iDevVideoPlay->NextPictureL()); + + while ((picture != NULL) && (status == KErrNone)) + { + PRINT((_L("CTRVideoDecoderClient::Pause(), Sending picture [0x%x] back to decoder"), picture)) + + iDevVideoPlay->ReturnPicture(picture); + picture = NULL; + + TRAP(status, picture = iDevVideoPlay->NextPictureL()); + } + + // Input buffer is not valid anymore + iInputBuffer = NULL; + + iPause = ETrue; + + PRINT((_L("CTRVideoDecoderClient::Pause(), Out"))) + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::ResumeL +// Resumes decoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::ResumeL() + { + PRINT((_L("CTRVideoDecoderClient::ResumeL(), In"))) + + // Start decoding + if (iFatalError == KErrNone) + { + iDevVideoPlay->Resume(); + } + + if (!iInputBuffer) + { + // Get buffer from the decoder to fill + iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize); + } + + // Reset ts monitor + iLastTimestamp = -1; + + iPause = EFalse; + + PRINT((_L("CTRVideoDecoderClient::ResumeL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoNewBuffers() +// New buffers are available +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoNewBuffers() + { + TInt status = KErrNone; + + + if (iStop) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewBuffers(), Stop was already called, nothing to do"))) + return; + } + + // One or more new empty input buffers are available + if (!iInputBuffer) + { + // Get buffer from the decoder to fill + TRAP(status, iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize)); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewBuffers(), GetBufferL status[%d]"), status)) + iObserver.MtrdvcoFatalError(status); + return; + } + + if (!iInputBuffer) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewBuffers(), There are available buffer, but decoder returned NULL"))) + + // Report an error or wait for the next MdvpoNewBuffers ?: Wait, GetBufferL is called when client send new coded buffer. + //iObserver.MtrdvcoFatalError(KErrAlreadyExists); + return; + } + } + + if (iCodedBuffer) + { + CCMRMediaBuffer* codedBuffer = iCodedBuffer; + + // Reset buffer ptr + iCodedBuffer = NULL; + + // Send coded buffer, since the client has already done request + TRAP(status, this->SendBufferL(codedBuffer)); + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewBuffers(), Send buffer error[%d]"), status)) + iObserver.MtrdvcoFatalError(status); + return; + } + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::WriteCodedBufferL +// Writes coded data to decoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::WriteCodedBufferL(CCMRMediaBuffer* aBuffer) + { + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), In"))) + CCMRMediaBuffer::TBufferType bufferType; + + if (!aBuffer) + { + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), Input buffer is invalid, Leave"))) + User::Leave(KErrArgument); + } + + if (iFatalError != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), FatalError was reported by decoder"))) + + // Return coded buffer + iObserver.MtrdvcoReturnCodedBuffer(aBuffer); + return; + } + + TTimeIntervalMicroSeconds ts = aBuffer->TimeStamp(); + + if ( ts <= iLastTimestamp) + { + // Prevent propagation of the error now + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), Client sends invalid data (ts field), Leave"))) + User::Leave(KErrArgument); + } + else + { + iLastTimestamp = ts; + } + + if (aBuffer->BufferSize() <= 0) + { + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), Input data buffer is invalid (empty), Leave"))) + User::Leave(KErrArgument); + } + + bufferType = aBuffer->Type(); + + if ( ( bufferType != CCMRMediaBuffer::EVideoH263 ) && + ( bufferType != CCMRMediaBuffer::EVideoMPEG4 ) ) // : Add H264 + { + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), [%d] This data type is not supported, Leave"), aBuffer->Type() )) + User::Leave(KErrNotSupported); + } + + if (!iInputBuffer) + { + // Request new empty buffer + iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize); + } + + if (iInputBuffer) + { + this->SendBufferL(aBuffer); + } + else + { + iCodedBuffer = aBuffer; + } + + PRINT((_L("CTRVideoDecoderClient::WriteCodedBufferL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::SendBufferL +// Sends buffer to decoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::SendBufferL(CCMRMediaBuffer* aBuffer) + { + PRINT((_L("CTRVideoDecoderClient::SendBufferL(), In"))) + + if (iStop) + { + PRINT((_L("CTRVideoDecoderClient::SendBufferL(), Stop was already called, nothing to do, out"))) + iObserver.MtrdvcoReturnCodedBuffer(aBuffer); + return; + } + + PRINT((_L("CTRVideoDecoderClient::SendBufferL(), iInputBuffer[%d], aBuffer[%d]"), iInputBuffer->iData.MaxLength(), + aBuffer->BufferSize() )) + + if ( iInputBuffer->iData.MaxLength() < aBuffer->BufferSize() ) + { + PRINT((_L("CTRVideoDecoderClient::SendBufferL(), buffer length exceeds max length"))) + User::Leave(KErrOverflow); + } + + iInputBuffer->iData.Copy( aBuffer->Data().Ptr(), aBuffer->BufferSize() ); + iInputBuffer->iData.SetLength( aBuffer->BufferSize() ); + + // Data unit presentation timestamp. Valid if EPresentationTimestamp is set in the options. + // If the input bitstream does not contain timestamp information, this field should be valid, + // otherwise pictures cannot be displayed at the correct time. If the input bitstream contains + // timestamp information (such as the TR syntax element of H.263 bitstreams) and valid + // iPresentationTimestamp is provided, the value of iPresentationTimestamp is used in playback. + iInputBuffer->iOptions = TVideoInputBuffer::EPresentationTimestamp; + iInputBuffer->iPresentationTimestamp = aBuffer->TimeStamp(); + /*Other data: TBC*/ + + TVideoInputBuffer* inputBuffer = iInputBuffer; + + // Reset InputBuffer ptr + iInputBuffer = NULL; + + // Write data to decoder + iDevVideoPlay->WriteCodedDataL(inputBuffer); + + // return buffer only after it's writtent to decoder (client could write next buffer synchronously from observer call) + // Return buffer to the client immediately after copying + iObserver.MtrdvcoReturnCodedBuffer(aBuffer); + + PRINT((_L("CTRVideoDecoderClient::SendBufferL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoNewPictures +// New decoded pictures available from decoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoNewPictures() + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewPictures(), In"))) + + TInt status = KErrNone; + + // 1 or more decoded pictures are available + if (!iDecodedPicture) + { + // Get new picture + TRAP(status, iDecodedPicture = iDevVideoPlay->NextPictureL()); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoNewPictures(), NextPicture status[%d]"), status)) + iObserver.MtrdvcoFatalError(status); + return; + } + + if (!iDecodedPicture) + { + // Error: DevVideo notified of new buffers, but returns NULL + PRINT((_L("CTRVideoDecoderClient::MdvpoNewPictures(), DevVideo notified of new buffers, but returns NULL"))) + iObserver.MtrdvcoFatalError(KErrAlreadyExists); + return; + } + + // Send new picture to the client + iObserver.MtrdvcoNewPicture(iDecodedPicture); + } + else + { + // Previous picture still was not returned by the client, nothing to do. + // SetActive(); // ??? + } + + PRINT((_L("CTRVideoDecoderClient::MdvpoNewPictures(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::ReturnPicture +// Returns picture +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::ReturnPicture(TVideoPicture* aPicture) + { + PRINT((_L("CTRVideoDecoderClient::ReturnPicture(), In"))) + TInt status = KErrNone; + + + iDevVideoPlay->ReturnPicture(aPicture); + + // Reset decoded picture + iDecodedPicture = NULL; + + if (iPause) + { + // Nothing else to do when paused + PRINT((_L("CTRVideoDecoderClient::ReturnPicture(), Out"))) + return; + } + + TRAP(status, iDecodedPicture = iDevVideoPlay->NextPictureL()); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoDecoderClient::ReturnPicture(), NextPicture status[%d]"), status)) + iObserver.MtrdvcoFatalError(status); + return; + } + + if (iDecodedPicture) + { + // Send new picture to the client + iObserver.MtrdvcoNewPicture(iDecodedPicture); + } + + PRINT((_L("CTRVideoDecoderClient::ReturnPicture(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::StopL +// Stops decoding synchronously +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::StopL() + { + PRINT((_L("CTRVideoDecoderClient::StopL(), In"))) + + iStop = ETrue; + iPause = EFalse; + + if (iFatalError == KErrNone) + { + iDevVideoPlay->Stop(); + } + + PRINT((_L("CTRVideoDecoderClient::StopL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::AsyncStopL +// Stops decoding asynchronously +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::AsyncStopL() + { + PRINT((_L("CTRVideoDecoderClient::StopL(), Async In"))) + + if (iFatalError == KErrNone) + { + iDevVideoPlay->InputEnd(); + } + + iStop = ETrue; + + PRINT((_L("CTRVideoDecoderClient::StopL(), Async Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoStreamEnd +// Indicates when stream end is reached +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoStreamEnd() + { + PRINT((_L("CTRVideoDecoderClient::MdvpoStreamEnd()"))) + iObserver.MtrdvcoDecStreamEnd(); + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoReturnPicture +// Returns a used input video picture back to the caller. The picture memory can be re-used or freed (only relevant to postprocessor) +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoReturnPicture(TVideoPicture* /*aPicture*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoReturnPicture()"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoSupplementalInformation +// Sends SupplementalInformation +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoSupplementalInformation(const TDesC8& /*aData*/, + const TTimeIntervalMicroSeconds& /*aTimestamp*/, + const TPictureId& /*aPictureId*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoSupplementalInformation()"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoPictureLoss +// Back channel information from the decoder, indicating a picture loss without specifying the lost picture +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoPictureLoss() + { + PRINT((_L("CTRVideoDecoderClient::MdvpoPictureLoss(), report an error"))) + iObserver.MtrdvcoFatalError(KErrAbort); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoPictureLoss +// Back channel information from the decoder, indicating the pictures that have been lost +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoPictureLoss(const TArray< TPictureId >& /*aPictures*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoPictureLoss(), pictureId: report an error"))) + iObserver.MtrdvcoFatalError(KErrAbort); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoSliceLoss +// Reports that slice is lost +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoSliceLoss(TUint /*aFirstMacroblock*/, TUint /*aNumMacroblocks*/, + const TPictureId& /*aPicture*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoSliceLoss()"))) + // This error is not considered a s fatal for decoder or application, nothing to do + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoReferencePictureSelection +// Back channel information from the decoder, indicating a reference picture selection request. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoReferencePictureSelection(const TDesC8& /*aSelectionData*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoReferencePictureSelection()"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoTimedSnapshotComplete +// Called when a timed snapshot request has been completed. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoTimedSnapshotComplete(TInt /*aError*/, TPictureData* /*aPictureData*/, + const TTimeIntervalMicroSeconds& /*aPresentationTimestamp*/, + const TPictureId& /*aPictureId*/) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoTimedSnapshotComplete()"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MdvpoFatalError +// Reports the fatal error to the client +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MdvpoFatalError(TInt aError) + { + PRINT((_L("CTRVideoDecoderClient::MdvpoFatalError(), error[%d]"), aError)) + iFatalError = aError; + iObserver.MtrdvcoFatalError(iFatalError); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::EstimateDecodeFrameTimeL +// Returns a time estimate on long it takes to decode one frame +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TReal CTRVideoDecoderClient::EstimateDecodeFrameTimeL(const TTRVideoFormat& aInput, TInt aCodecType) + { + if (iUid == TUid::Null()) + { + PRINT((_L("CTRVideoDecoderClient::EstimateDecodeFrameTimeL(), no decoder selected yet"))) + User::Leave(KErrNotReady); + } + + TReal time = 0.0; + + // Select the predefined constant using the current settings + if (aCodecType == EH263) + { + time = iAcceleratedCodecSelected ? KTRDecodeTimeFactorH263HW : KTRDecodeTimeFactorH263SW; + } + else if (aCodecType == EH264) + { + time = iAcceleratedCodecSelected ? KTRDecodeTimeFactorH264HW : KTRDecodeTimeFactorH264SW; + } + else + { + time = iAcceleratedCodecSelected ? KTRDecodeTimeFactorMPEG4HW : KTRDecodeTimeFactorMPEG4SW; + } + + // Multiply the time by the resolution of the input frame + time *= static_cast(aInput.iSize.iWidth + aInput.iSize.iHeight) * KTRTimeFactorScale; + + PRINT((_L("CTRVideoDecoderClient::EstimateDecodeFrameTimeL(), decode frame time: %.2f"), time)) + + return time; + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::SetDecoderScaling +// Checks if decoder supports scaling and enables scaling if supported +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CTRVideoDecoderClient::SetDecoderScaling(TSize& aInputSize, TSize& aOutputSize) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), In"))) + + CPostProcessorInfo* ppInfo = NULL; + TBool scalingSupported = EFalse; + + // Check that the given sizes are valid + if( (aInputSize.iWidth == 0) || (aInputSize.iHeight == 0) || + (aOutputSize.iWidth == 0) || (aOutputSize.iHeight == 0) ) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), invalid input/output size"))) + return EFalse; + } + + iScalingInUse = EFalse; + iScalingWithDeblocking = EFalse; + + if( aInputSize == aOutputSize ) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), scaling disabled"))) + return EFalse; + } + + // Get post processor info + TRAPD( status, ppInfo = iDevVideoPlay->PostProcessorInfoLC( iUid ); CleanupStack::Pop( ppInfo ) ); + + if( (status != KErrNone) || !ppInfo ) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), getting info from [0x%x] failed"), iUid.iUid )) + return EFalse; + } + + if( ppInfo->SupportsArbitraryScaling() ) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), arbitrary scaling supported"))) + scalingSupported = ETrue; + } + else if( (aInputSize.iWidth * aOutputSize.iHeight) != (aInputSize.iHeight * aOutputSize.iWidth) ) + { + // Aspect ratio needs to be changed but decoder does not support arbitrary scaling => not supported + scalingSupported = EFalse; + } + else + { + RArray scaleFactors = ppInfo->SupportedScaleFactors(); + + for( TInt i = 0; i < scaleFactors.Count(); ++i ) + { + if( (aInputSize.iWidth * scaleFactors[i].iScaleNum) == (aOutputSize.iWidth * scaleFactors[i].iScaleDenom) ) + { + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), supported scale factors found"))) + scalingSupported = ETrue; + break; + } + } + } + + if( scalingSupported ) + { + if( ppInfo->SupportsCombination( EPpScale | EPpDeblocking ) ) + { + // Deblocking should be used with scaling if supported + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), deblocking supported"))) + iScalingWithDeblocking = ETrue; + } + + iScalingInUse = ETrue; + iScaledOutputSize = aOutputSize; + } + + // Delete codec info + delete ppInfo; + + PRINT((_L("CTRVideoDecoderClient::SetDecoderScaling(), Out"))) + + return scalingSupported; + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::EnableResourceObserver +// Enable / Disable resourece observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::EnableResourceObserver(TBool aEnable) + { + PRINT((_L("CTRVideoDecoderClient::EnableResourceObserver(), In"))) + + iVideoResourceHandlerCI = (MMmfVideoResourceHandler*)iDevVideoPlay->CustomInterface( iHwDeviceId, KUidMmfVideoResourceManagement ); + PRINT((_L("CTRVideoDecoderClient::EnableResourceObserver(), iVideoResourceHandlerCI[0x%x]"), iVideoResourceHandlerCI)) + + if (iVideoResourceHandlerCI) + { + if (aEnable) + { + iVideoResourceHandlerCI->MmvrhSetObserver(this); + PRINT((_L("CTRVideoDecoderClient::EnableResourceObserver(), Enabled"))) + } + else + { + iVideoResourceHandlerCI->MmvrhSetObserver(NULL); + } + } + + PRINT((_L("CTRVideoDecoderClient::EnableResourceObserver(), Out"))) + } + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MmvroResourcesLost +// Indicates that a media device has lost its resources +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MmvroResourcesLost(TUid /*aMediaDevice*/) + { + iObserver.MtrdvcoResourcesLost(ETrue); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoDecoderClient::MmvroResourcesRestored +// Indicates that a media device has regained its resources +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoDecoderClient::MmvroResourcesRestored(TUid /*aMediaDevice*/) + { + iObserver.MtrdvcoResourcesRestored(); + } + + +// End of file