diff -r 000000000000 -r 951a5db380a0 videoeditorengine/vedtranscoder/src/Ctrvideoencoderclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/vedtranscoder/src/Ctrvideoencoderclient.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1824 @@ +/* +* 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 encoder client. +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include "ctrtranscoder.h" +#include "ctrvideoencoderclient.h" +#include "ctrdevvideoclientobserver.h" +#include "ctrsettings.h" +#include "ctrhwsettings.h" + + +// MACROS +#define TRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CTRANSCODERVIDEOENCODERCLIENT"), -10000)) + + +// CONSTANTS + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CTRVideoEncoderClient* CTRVideoEncoderClient::NewL(MTRDevVideoClientObserver& aObserver) + { + PRINT((_L("CTRVideoEncoderClient::NewL(), In"))) + CTRVideoEncoderClient* self = new (ELeave) CTRVideoEncoderClient(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + + PRINT((_L("CTRVideoEncoderClient::NewL(), Out"))) + return self; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::CTRVideoEncoderClient +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CTRVideoEncoderClient::CTRVideoEncoderClient(MTRDevVideoClientObserver& aObserver) : + iObserver(aObserver) + { + iDevVideoRecord = NULL; + iOutputMediaBuffer = NULL; + iCompresedFormat = NULL; + iUid = TUid::Null(); + iFallbackUid = TUid::Null(); + iRealTime = EFalse; + iState = ETRNone; + iCodingOptions.iSyncIntervalInPicture = 0; + iCodingOptions.iHeaderExtension = 0; + iCodingOptions.iDataPartitioning = EFalse; + iCodingOptions.iReversibleVLC = EFalse; + iSrcRate = 0.0; + iVolHeaderSent = EFalse; + iRemoveHeader = EFalse; + iVolLength = 0; + iRateOptions.iControl = EBrControlStream; + iRateOptions.iPictureRate = KTRTargetFrameRateDefault; + iRateOptions.iBitrate = KTRMaxBitRateH263Level10; + iBitRateSetting = EFalse; + iFatalError = KErrNone; + iErrorRate = 0.0; + iVolHeader = KNullDesC8; + iVideoBufferManagementCI = NULL; + iLastTimestamp = -1; + iAcceleratedCodecSelected = EFalse; + iSetRandomAccessPoint = EFalse; + iNumH264SPSPPS = 0; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::ConstructL() + { + iDevVideoRecord = CMMFDevVideoRecord::NewL(*this); + iOutputMediaBuffer = new(ELeave)CCMRMediaBuffer; + } + + +// --------------------------------------------------------- +// CTRVideoEncoderClient::~CTRVideoEncoderClient() +// Destructor +// --------------------------------------------------------- +// +CTRVideoEncoderClient::~CTRVideoEncoderClient() + { + PRINT((_L("CTRVideoEncoderClient::~CTRVideoEncoderClient(), In"))) + + if (iDevVideoRecord) + { + delete iDevVideoRecord; + iDevVideoRecord = NULL; + } + + if (iCompresedFormat) + { + delete iCompresedFormat; + } + + if (iOutputMediaBuffer) + { + delete iOutputMediaBuffer; + } + + PRINT((_L("CTRVideoEncoderClient::~CTRVideoEncoderClient(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SupportsInputFormat +// Checks whether given input format is supported +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CTRVideoEncoderClient::SupportsCodec(const TDesC8& aFormat, const TDesC8& aShortFormat, TInt aUid, TInt aFallbackUid) + { + TBool supports = EFalse; + TBool preferredFound = EFalse; + TBool fallbackFound = EFalse; + + if (iDevVideoRecord) + { + RArray encoders; + + TRAPD( status, iDevVideoRecord->FindEncodersL(aShortFormat, 0/*aPreProcType*/, encoders, EFalse/*aExactMatch*/) ); + + if( status != KErrNone ) + { + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), status[%d]"), status)) + supports = EFalse; + } + else if( encoders.Count() <= 0 ) + { + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), No encoders found"))) + supports = EFalse; + } + else + { + + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), %d encoders found"), encoders.Count() )) + + // Check if any of the found encoders matches with the given Uids + for( TInt i = 0; i < encoders.Count(); ++i ) + { + + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), found codec 0x%x"), encoders[i].iUid)) + + if( encoders[i].iUid == aUid ) + { + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), preferred found"))) + iUid = encoders[i]; + preferredFound = ETrue; + } + if( encoders[i].iUid == aFallbackUid ) + { + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), fallback found"))) + iFallbackUid = encoders[i]; + fallbackFound = ETrue; + } + + if( preferredFound && fallbackFound ) + { + // No need to search anymore + break; + } + } + } + + encoders.Reset(); + encoders.Close(); + } + +#if !( defined (__WINS__) || defined (__WINSCW__) ) + if( !preferredFound ) +#else + if( !preferredFound && !fallbackFound ) +#endif + { + // Preferred encoder was not found => Probably the given encoder Uid is wrong + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), No supported encoders found"))) + supports = EFalse; + } + else + { + PRINT((_L("CTRVideoEncoderClient::SupportsCodec(), Supported encoder found: 0x%x"), iUid.iUid)) + iMimeType = aFormat; + iShortMimeType = aShortFormat; + supports = ETrue; + } + + return supports; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetCodecParametersL +// Sets codec parameters +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetCodecParametersL(TInt aCodecType, TInt aCodecLevel, const TTRVideoFormat& aInputFormat, + const TTRVideoFormat& aOutputFormat) + { + PRINT((_L("CTRVideoEncoderClient::SetCodecParametersL(), In"))) + TInt status = KErrNone; + iCodecType = aCodecType; + iCodecLevel = aCodecLevel; + iPictureSize = aOutputFormat.iSize; + iOutputDataType = aOutputFormat.iDataType; + + // RAW YUV + iUncompressedFormat.iDataFormat = EYuvRawData; + + // U & V samples are taken from the middle of four luminance samples + // (as specified in H.263 spec) + switch ( aInputFormat.iDataType ) + { + case CTRTranscoder::ETRYuvRawData420: + { + iUncompressedFormat.iYuvFormat.iPattern = EYuv420Chroma2; + break; + } + + case CTRTranscoder::ETRYuvRawData422: + { + iUncompressedFormat.iYuvFormat.iPattern = EYuv422Chroma2; + break; + } + + default: + { + iUncompressedFormat.iYuvFormat.iPattern = EYuv420Chroma2; + break; + } + } + + // Output format + if (!iCompresedFormat) + { + iCompresedFormat = CCompressedVideoFormat::NewL( iMimeType ); + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + + if (status != KErrNone) + { + // Try again with the fallback encoder if one exists + if( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iFallbackUid) ); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoEncoderClient::SetCodecParametersL(), Failed to get codec info"))) + User::Leave(KErrNotSupported); + } + + PRINT((_L("CTRVideoEncoderClient::SetCodecParametersL(), Reverting to fallback encoder"))) + + // Fallback ok, take it + iUid = iFallbackUid; + } + else + { + PRINT((_L("CTRVideoEncoderClient::SetCodecParametersL(), No suitable encoders found"))) + User::Leave(KErrNotSupported); + } + } + + // AA Set codec here (final hwdevice Uid should be known before checking CI buffermanag support) + // Select encoder first + this->SelectEncoderL(); + + PRINT((_L("CTRVideoEncoderClient::SetCodecParametersL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::CheckCodecInfoL +// Checks codec info +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CTRVideoEncoderClient::CheckCodecInfoL(TUid aUid) + { + CVideoEncoderInfo* encoderInfo = NULL; // Encoder info for retrieving capabilities + iMaxFrameRate = 0; + TInt status = KErrNone; + TUint32 dataUnitType = 0; + TBool accelerated = EFalse; + + switch(iOutputDataType) + { + case CTRTranscoder::ETRDuCodedPicture: + { + dataUnitType = EDuCodedPicture; + break; + } + + case CTRTranscoder::ETRDuVideoSegment: + { + dataUnitType = EDuVideoSegment; + break; + } + + default: + { + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), should leave at the earlier stage, panic"))) + TRASSERT(0); + } + } + + // Check encoder + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), getting info from [0x%x]"), aUid.iUid )) + encoderInfo = iDevVideoRecord->VideoEncoderInfoLC( aUid ); + + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), info [0x%x]"), encoderInfo )) + + if (!encoderInfo) + { + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), getting info from [0x%x] failed[%d]"), aUid.iUid, status )) + User::Leave(KErrNotSupported); + } + else + { + // Check input format + // 1. retrieve supported formats from encoder hwdevice (since exact options are unknown) + RArray supportedInputFormats = encoderInfo->SupportedInputFormats(); + + TInt formatCount = supportedInputFormats.Count(); + + if (formatCount <= 0) + { + supportedInputFormats.Close(); + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), There are no supported input formats") )) + User::Leave(KErrNotSupported); + } + else + { + TUncompressedVideoFormat uncFormat; + TBool found = EFalse; + TInt pattern1, pattern2; + TInt dataLayout; + + if (iUncompressedFormat.iYuvFormat.iPattern == EYuv420Chroma2) + { + pattern1 = EYuv420Chroma1; + pattern2 = EYuv420Chroma2; + dataLayout = EYuvDataPlanar; + } + else + { + pattern1 = EYuv422Chroma1; + pattern2 = EYuv422Chroma2; + dataLayout = EYuvDataInterleavedBE; + } + + // Check the most important paramers + for ( TInt i = 0; i < formatCount; i ++ ) + { + uncFormat = supportedInputFormats[i]; + + if ( (uncFormat.iDataFormat == iUncompressedFormat.iDataFormat) && + (uncFormat.iYuvFormat.iDataLayout == dataLayout) && + ( (uncFormat.iYuvFormat.iPattern == pattern1) || + (uncFormat.iYuvFormat.iPattern == pattern2) ) ) + { + // Assign the rest of parameters + iUncompressedFormat = uncFormat; + + if ( iCodecType != EH263 ) + { + // Set aspect ratio to 1:1 (square) + iUncompressedFormat.iYuvFormat.iAspectRatioNum = 1; + iUncompressedFormat.iYuvFormat.iAspectRatioDenom = 1; + } + + found = ETrue; + break; + } + } + + if (!found) + { + supportedInputFormats.Close(); + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), Supported format is not found") )) + User::Leave(KErrNotSupported); + } + } + + /*if ( !encoderInfo->SupportsOutputFormat(*iCompresedFormat) ) // comment until symbian error is fixed + { + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), Output format is not supported"))) + status = KErrNotSupported; + } + else */ + if ( (encoderInfo->SupportedDataUnitTypes() & dataUnitType) != dataUnitType ) + { + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), There's no support for this DUType"))) + status = KErrNotSupported; + } + else + { + // Get max rate for requested image format + RArray rateAndSize = encoderInfo->MaxPictureRates(); + TUint rates = rateAndSize.Count(); + + TSize picSize = iPictureSize; + if ( picSize == TSize(640, 352) ) // Use VGA max frame rate for VGA 16:9 + picSize = TSize(640, 480); + + for ( TUint i = 0; i < rates; i++ ) + { + if ( rateAndSize[i].iPictureSize == picSize ) + { + status = KErrNone; + iMaxFrameRate = rateAndSize[i].iPictureRate; + PRINT((_L("CTRVideoEncoderClient::CheckCodecInfoL(), Needed picture size found!"))) + break; + } + + status = KErrNotSupported; + } + } + } + + accelerated = encoderInfo->Accelerated(); + + // Delete codec info + CleanupStack::PopAndDestroy(encoderInfo); + + if (status != KErrNone) + { + User::Leave(status); + } + + return accelerated; + } + + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetBitRate +// Sets video bitrate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetBitRate(TUint aBitRate) + { + if ( (iState == ETRInitialized) || (iState == ETRRunning) || (iState == ETRPaused) ) + { + iRateOptions.iBitrate = aBitRate; + iRateOptions.iPictureQuality = KTRPictureQuality; + iRateOptions.iQualityTemporalTradeoff = KTRQualityTemporalTradeoff; + + if (iRealTime) + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffRT; + } + else + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffNonRT; + } + + // Set bit rate to Encoder + iDevVideoRecord->SetRateControlOptions(0/*Layer 0 is supported*/, iRateOptions); + iBitRateSetting = ETrue; + } + else + { + // Keep bit rate and set it later + iRateOptions.iBitrate = aBitRate; + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetRealTime +// Sets encoder mode to operate real-time +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetRealTime(TBool aRealTime) + { + iRealTime = aRealTime; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetFrameRate +// Sets frame rate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetFrameRate(TReal& aFrameRate) + { + if ( (iState == ETRInitialized) || (iState == ETRRunning) || (iState == ETRPaused) ) + { + iRateOptions.iPictureRate = aFrameRate; + + // The target frame rate must not be greater than the source frame rate + if ( (iSrcRate > 0.0) && (iRateOptions.iPictureRate > iSrcRate) ) + { + iRateOptions.iPictureRate = iSrcRate; + } + + if (iRealTime) + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffRT; + } + else + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffNonRT; + } + + // Set framerate rate to Encoder + iDevVideoRecord->SetRateControlOptions(0/*Layer 0 is supported*/, iRateOptions); + } + else + { + // Keep frame rate and set it later + iRateOptions.iPictureRate = aFrameRate; + + // The target frame rate must not be greater than the source frame rate + if ( (iSrcRate > 0.0) && (iRateOptions.iPictureRate > iSrcRate) ) + { + iRateOptions.iPictureRate = iSrcRate; + } + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetChannelBitErrorRate +// Sets channel bit error rate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetChannelBitErrorRate(TReal aErrorRate) + { + if ( (iState == ETRInitialized) || (iState == ETRRunning) || (iState == ETRPaused) ) + { + // Run-time setting + iDevVideoRecord->SetChannelBitErrorRate(0/*Error protection level number*/, aErrorRate, 0.0/*Std deviation*/); + } + else + { + iErrorRate = aErrorRate; + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetVideoCodingOptionsL +// Sets video coding options +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetVideoCodingOptionsL(TTRVideoCodingOptions& aOptions) + { + iCodingOptions = aOptions; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::GetVideoBitRateL +// Gets video bitrate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint CTRVideoEncoderClient::GetVideoBitRateL() + { + return iRateOptions.iBitrate; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::GetFrameRateL +// Gets frame rate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TReal CTRVideoEncoderClient::GetFrameRateL() + { + return iRateOptions.iPictureRate; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetInputFrameRate +// Sets source framerate +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetInputFrameRate(TReal aFrameRate) + { + iSrcRate = aFrameRate; + + // The target frame rate must not be greater than the source frame rate + if ( (iSrcRate > 0.0) && (iRateOptions.iPictureRate > iSrcRate) ) + { + iRateOptions.iPictureRate = iSrcRate; + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::InitializeL +// Initializes encoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::InitializeL() + { + PRINT((_L("CTRVideoEncoderClient::InitializeL(), In"))) + TVideoDataUnitType dataUnitType = EDuCodedPicture; + TEncoderBufferOptions bufferOptions; + TUint maxBufferSize = 0; + + + // Give Init settings + // 1. Set output format. Output format was already set in SetCodecParametersL + switch(iOutputDataType) + { + case CTRTranscoder::ETRDuCodedPicture: + { + dataUnitType = EDuCodedPicture; + bufferOptions.iMinNumOutputBuffers = KTRMinNumberOfBuffersCodedPicture; + break; + } + + case CTRTranscoder::ETRDuVideoSegment: + { + dataUnitType = EDuVideoSegment; + bufferOptions.iMinNumOutputBuffers = KTRMinNumberOfBuffersVideoSegment; + break; + } + + default: + { + // Should never happend. Encoder does not support uncompressed output format. + TRASSERT(0); + } + } + + TVideoDataUnitEncapsulation dataUnitEncapsulation = EDuElementaryStream; + + // Use generic payload encapsulation for H.264 + if (iCodecType == EH264) + { + dataUnitEncapsulation = EDuGenericPayload; + } + + iDevVideoRecord->SetOutputFormatL(iHwDeviceId, *iCompresedFormat, dataUnitType, dataUnitEncapsulation, EFalse); + + // 2. Set input format + iDevVideoRecord->SetInputFormatL(iHwDeviceId, iUncompressedFormat, iPictureSize); + + // 3. Buffer options + bufferOptions.iMaxPreEncoderBufferPictures = bufferOptions.iMinNumOutputBuffers; + bufferOptions.iHrdVbvSpec = EHrdVbvNone; + bufferOptions.iHrdVbvParams.Set(NULL, 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 KTRH263CodecLevel45: + { + maxBufferSize = KTRMaxBufferSizeLevel45; + 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 KTRMPEG4CodecLevel1: + case KTRMPEG4CodecLevel0: + { + maxBufferSize = KTRMaxBufferSizeLevel0; + break; + } + + case KTRMPEG4CodecLevel0b: + { + maxBufferSize = KTRMaxBufferSizeLevel0b; + break; + } + + case KTRMPEG4CodecLevel2: + { + maxBufferSize = KTRMaxBufferSizeLevel2; + break; + } + + case KTRMPEG4CodecLevel3: + { + maxBufferSize = KTRMaxBufferSizeLevel3; + break; + } + + case KTRMPEG4CodecLevel4a: + { + maxBufferSize = KTRMaxBufferSizeLevel4a; + break; + } + + default: + { + maxBufferSize = KTRMaxBufferSizeLevel0; + } + } + + bufferOptions.iMaxOutputBufferSize = maxBufferSize; + bufferOptions.iMaxCodedPictureSize = bufferOptions.iMaxOutputBufferSize; + + if ((iCodecType != EH263) && (iCodingOptions.iSyncIntervalInPicture > 0)) + { + // Set segment target size + if ( iCodingOptions.iSyncIntervalInPicture < KTRMinSegmentSize ) + { + bufferOptions.iMaxCodedSegmentSize = KTRMinSegmentSize; + } + else if (iCodingOptions.iSyncIntervalInPicture > bufferOptions.iMaxCodedPictureSize) + { + bufferOptions.iMaxCodedSegmentSize = bufferOptions.iMaxCodedPictureSize; + } + else + { + bufferOptions.iMaxCodedSegmentSize = iCodingOptions.iSyncIntervalInPicture; + } + } + else + { + // Set segment size to max video coded picture size + bufferOptions.iMaxCodedSegmentSize = bufferOptions.iMaxCodedPictureSize; + } + + PRINT((_L("CTRVideoEncoderClient::InitializeL(), iMaxOutputBufferSize[%d], iMinNumOutputBuffers[%d]"), + bufferOptions.iMaxOutputBufferSize, bufferOptions.iMinNumOutputBuffers )) + + iDevVideoRecord->SetBufferOptionsL(bufferOptions); + + // 4. Random access point + TReal accessRate = KTRDefaultAccessRate; /* ~0.2 fps */ + + if (iCodingOptions.iMinRandomAccessPeriodInSeconds > 0) + { + accessRate = 1.0 / TReal(iCodingOptions.iMinRandomAccessPeriodInSeconds); + } + + PRINT((_L("CTRVideoEncoderClient::InitializeL(), RandomAcessRate[%f]"), accessRate)); + iDevVideoRecord->SetMinRandomAccessRate(accessRate); + + // 5. Other coding options + if (iCodecType == EH263) + { + if (iCodingOptions.iSyncIntervalInPicture > 0) + { + TH263VideoMode h263CodingOptions; + + h263CodingOptions.iAllowedPictureTypes = EH263PictureTypeI | EH263PictureTypeP; + h263CodingOptions.iForceRoundingTypeToZero = ETrue; + h263CodingOptions.iPictureHeaderRepetition = 0; + h263CodingOptions.iGOBHeaderInterval = iCodingOptions.iSyncIntervalInPicture; + + TPckgC h263OptionsPckg(h263CodingOptions); + iDevVideoRecord->SetCodingStandardSpecificOptionsL(h263OptionsPckg); + } + } + else if (iCodecType == EH264) + { + // H.264 options + TAvcVideoMode avcCodingOptions; + + avcCodingOptions.iAllowedPictureTypes = EAvcPictureTypeI | EAvcPictureTypeP; + avcCodingOptions.iFlexibleMacroblockOrder = EFalse; + avcCodingOptions.iRedundantPictures = EFalse; + avcCodingOptions.iDataPartitioning = iCodingOptions.iDataPartitioning; + avcCodingOptions.iFrameMBsOnly = ETrue; + avcCodingOptions.iMBAFFCoding = EFalse; + avcCodingOptions.iEntropyCodingCABAC = EFalse; + avcCodingOptions.iWeightedPPrediction = EFalse; + avcCodingOptions.iWeightedBipredicitonMode = 0; + avcCodingOptions.iDirect8x8Inference = EFalse; + + TPckgC avc4OptionsPckg(avcCodingOptions); + iDevVideoRecord->SetCodingStandardSpecificOptionsL(avc4OptionsPckg); + } + else + { + // Mpeg4 options + TMPEG4VisualMode mpeg4CodingOptions; + mpeg4CodingOptions.iShortHeaderMode = EFalse; + mpeg4CodingOptions.iMPEG4VisualNormalMPEG4Mode.iHeaderExtension = iCodingOptions.iHeaderExtension; + mpeg4CodingOptions.iMPEG4VisualNormalMPEG4Mode.iDataPartitioning = iCodingOptions.iDataPartitioning; + mpeg4CodingOptions.iMPEG4VisualNormalMPEG4Mode.iReversibleVLC = iCodingOptions.iReversibleVLC; + + mpeg4CodingOptions.iMPEG4VisualNormalMPEG4Mode.iAllowedVOPTypes = EMPEG4VisualVOPTypeI; + + TPckgC mpeg4OptionsPckg(mpeg4CodingOptions); + iDevVideoRecord->SetCodingStandardSpecificOptionsL(mpeg4OptionsPckg); + } + + // Set source + if (iSrcRate <= 0.0) + { + iSrcRate = KTRDefaultSrcRate; /* ~15.0 fps */ + } + + iDevVideoRecord->SetSourceMemoryL(iSrcRate, ETrue, iRealTime); + + // Initialize devVideoRecord + iDevVideoRecord->Initialize(); + + // Set media buffer type + if (iCodecType == EH263) + { + // Set H.263 + iBufferType = CCMRMediaBuffer::EVideoH263; + } + else if (iCodecType == EH264) + { + // Set H.264 + iBufferType = CCMRMediaBuffer::EVideoMPEG4; // : What to set here? + } + else + { + // Set MPEG4 + iBufferType = CCMRMediaBuffer::EVideoMPEG4; + } + + PRINT((_L("CTRVideoEncoderClient::InitializeL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SelectEncoderL +// Selects encoder +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SelectEncoderL() + { + PRINT((_L("CTRVideoEncoderClient::SelectEncoderL(), In"))) + TInt status = KErrNone; + + if (iUid != TUid::Null()) + { + TRAP(status, iHwDeviceId = iDevVideoRecord->SelectEncoderL(iUid)); + } + else + { + // Probably the error already exists, if iUid == NULL; + status = KErrAlreadyExists; + } + + if (status != KErrNone) + { + // Try again with the fallback encoder if one exists + if( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + PRINT((_L("CTRVideoEncoderClient::SelectEncoderL(), Reverting to fallback encoder"))) + iUid = iFallbackUid; + } + else + { + PRINT((_L("CTRVideoEncoderClient::SelectDecoderL(), Failed to select encoder"))) + User::Leave(KErrNotSupported); + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoEncoderClient::SelectDecoderL(), Failed to get codec info"))) + User::Leave(KErrNotSupported); + } + + TRAP(status, iHwDeviceId = iDevVideoRecord->SelectEncoderL(iUid)); + + if (status != KErrNone) + { + PRINT((_L("CTRVideoEncoderClient::SelectDecoderL(), Failed to select encoder"))) + User::Leave(KErrNotSupported); + } + } + + PRINT((_L("CTRVideoEncoderClient::SelectEncoderL(), Out"))) + } + + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroInitializeComplete +// Informs init status with received error code +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroInitializeComplete(TInt aError) + { + if (aError == KErrNone) + { + iState = ETRInitialized; + } + else if ((aError == KErrHardwareNotAvailable) || (aError == KErrNotSupported)) + { + PRINT((_L("CTRVideoEncoderClient::MdvroInitializeComplete(), Error in initialization"))) + + // Map both error codes to the same + aError = KErrNotSupported; + + // Try again with the fallback encoder if one exists + while( (iFallbackUid != TUid::Null()) && (iFallbackUid.iUid != iUid.iUid) ) + { + PRINT((_L("CTRVideoEncoderClient::MdvroInitializeComplete(), Reverting to fallback encoder"))) + + iUid = iFallbackUid; + + // Devvideo must be recreated from scratch + if (iDevVideoRecord) + { + delete iDevVideoRecord; + iDevVideoRecord = NULL; + } + + TRAPD( status, iDevVideoRecord = CMMFDevVideoRecord::NewL(*this) ); + if (status != KErrNone) + { + // Something went wrong, let CTRTranscoderImp handle the error + PRINT((_L("CTRVideoEncoderClient::MdvroInitializeComplete(), Failed to create DevVideoRecord"))) + break; + } + + TRAP( status, iAcceleratedCodecSelected = CheckCodecInfoL(iUid) ); + if (status != KErrNone) + { + // Fallback encoder can not be used, let CTRTranscoderImp handle the error + PRINT((_L("CTRVideoEncoderClient::MdvroInitializeComplete(), Failed to get codec info"))) + break; + } + + TRAP( status, SelectEncoderL() ); + if (status != KErrNone) + { + // Fallback encoder can not be used, let CTRTranscoderImp handle the error + PRINT((_L("CTRVideoEncoderClient::MdvroInitializeComplete(), Failed to select encoder"))) + break; + } + + // We are now ready to reinitialize the encoder, let CTRTranscoderImp do it + aError = KErrHardwareNotAvailable; + break; + } + } + + iObserver.MtrdvcoEncInitializeComplete(aError); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::StartL +// Starts encoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::StartL() + { + PRINT((_L("CTRVideoEncoderClient::StartL(), In"))) + + if ( (iCodecType == EMpeg4) && (iVolHeader == KNullDesC8) ) + { + // Before starting the encoder, request config data + HBufC8* condigDecInfo = iDevVideoRecord->CodingStandardSpecificInitOutputLC(); + + if (condigDecInfo) + { + PRINT((_L("CTRVideoEncoderClient::StartL(), Vol header length[%d]"), condigDecInfo->Length())) + + if ( (condigDecInfo->Length() > 0) && (condigDecInfo->Length() <= KMaxDesC8Length /*256*/) ) + { + iVolHeader.Des().Copy( condigDecInfo->Des() ); + + // Keep vol length for further use + iVolLength = iVolHeader.Des().Length(); + PRINT((_L("CTRVideoEncoderClient::StartL(), VolLength[%d]"), iVolLength)) + } + + CleanupStack::PopAndDestroy(condigDecInfo); + } + else + { + PRINT((_L("CTRVideoEncoderClient::StartL(), Invalid codingDecInfo, leave"))) + User::Leave(KErrAlreadyExists); + } + + PRINT((_L("CTRVideoEncoderClient::StartL(), Out"))) + } + + + // Set Rate control options + if (!iBitRateSetting) + { + iRateOptions.iPictureQuality = KTRPictureQuality; + iRateOptions.iQualityTemporalTradeoff = KTRQualityTemporalTradeoff; + + if (iRealTime) + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffRT; + } + else + { + iRateOptions.iLatencyQualityTradeoff = KTRLatencyQualityTradeoffNonRT; + } + + iDevVideoRecord->SetRateControlOptions(0/*Layer 0 is supported*/, iRateOptions); + iBitRateSetting = ETrue; + } + + if ( (iCodecType != EH263) && (iCodingOptions.iSyncIntervalInPicture > 0) ) + { + // Set resync value (segment target size) + iDevVideoRecord->SetSegmentTargetSize(0/*aLayer*/, + iCodingOptions.iSyncIntervalInPicture/*aSizeBytes*/, + 0/*aSizeMacroblocks*/); + } + + // Start encoding + if (iFatalError == KErrNone) + { + iDevVideoRecord->Start(); + iState = ETRRunning; + } + + // Reset ts monitor + iLastTimestamp = -1; + + iSetRandomAccessPoint = EFalse; + + PRINT((_L("CTRVideoEncoderClient::StartL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::EncodePictureL +// Encodes video picture +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::EncodePictureL(TVideoPicture* aPicture) + { + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), In"))) + + if (aPicture) + { + if (iFatalError == KErrNone) + { + // Set rest of picture options + aPicture->iOptions = TVideoPicture::ETimestamp; + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), picture timestamp [%d]"), TInt(aPicture->iTimestamp.Int64()) )) + + TTimeIntervalMicroSeconds ts = aPicture->iTimestamp; + + if ( ts <= iLastTimestamp) + { + // Prevent propagation of the error now + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Picture timestamp less than previously encoded"))) + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Dropping picture!!!"))) + iObserver.MtrdvcoEncoderReturnPicture(aPicture); + + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Out"))) + return; + } + else + { + iLastTimestamp = ts; + } + + // If random access point was requested + if( iSetRandomAccessPoint ) + { + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Instant Refresh requested"))); + aPicture->iOptions |= TVideoPicture::EReqInstantRefresh; + iSetRandomAccessPoint = EFalse; + } + else + { + aPicture->iOptions &= ~(TVideoPicture::EReqInstantRefresh); + } + + aPicture->iData.iDataFormat = EYuvRawData; // Force data format to YUV + + iDevVideoRecord->WritePictureL(aPicture); + } + else + { + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Operation is not possible, since FatalError was reported by low-level[%d]"), iFatalError)) + return; + } + } + else + { + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Picture is not valid, leave"))) + User::Leave(KErrArgument); + } + + PRINT((_L("CTRVideoEncoderClient::EncodePictureL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroReturnPicture +// Returns picture +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroReturnPicture(TVideoPicture *aPicture) + { + iObserver.MtrdvcoEncoderReturnPicture(aPicture); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroNewBuffers +// New buffers are available in the system +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroNewBuffers() + { + TVideoOutputBuffer* newBuffer = NULL; + TInt status = KErrNone; + + + if ( (iCodecType == EMpeg4) && (!iVolHeaderSent) && (iVolHeader != KNullDesC8) ) + { + // Send vol header first to the client + iOutputMediaBuffer->Set( iVolHeader.Des(), + CCMRMediaBuffer::EVideoMPEG4DecSpecInfo, + iVolHeader.Des().Length(), + 0, + 0 ); + + iObserver.MtrdvcoNewBuffer(iOutputMediaBuffer); + iVolHeaderSent = ETrue; + + // VOS+VO+VOL header is now going to be stored to metadata, it must not be included in mediadata so remove it from the next buffer + iRemoveHeader = ETrue; + } + + // Get new buffer and forward it to the client + while( iDevVideoRecord->NumDataBuffers() > 0 ) + { + TRAP(status, newBuffer = iDevVideoRecord->NextBufferL()); + if (status != KErrNone) + { + PRINT((_L("CTRVideoEncoderClient::MdvroNewBuffers(), NextBufferL failed[%d]"), status)) + iObserver.MtrdvcoFatalError(status); + return; + } + + if (newBuffer) + { + PRINT((_L("CTRVideoEncoderClient::MdvroNewBuffers(), dataBuffer length[%d]"), newBuffer->iData.Length())) + + // Check data length if valid + if (newBuffer->iData.Length() <= 0) + { + // Data length is invalid + PRINT((_L("CTRVideoEncoderClient::MdvroNewBuffers(), encoder generates invalid bitstream, abort data processing"))) + iObserver.MtrdvcoFatalError(KErrAbort); + return; + } + + TBool outputMediaBufferSet = EFalse; + + // Remove vol header if needed from the bitstream + if ( iRemoveHeader ) + { + iRemoveHeader = EFalse; + + if ( iCodecType == EMpeg4 ) + { + // check if we need to remove VOS+VO+VOL header from the bitstream, since it is + // stored in metadata, and having it in 2 places may cause interoperability problems + + // Since the length of the vol is already known, remove that data from the beginning of + // the first buffer + if ( (iVolLength > 0) && (iVolLength < newBuffer->iData.Length()) ) + { + TPtr8* buffer = reinterpret_cast(&newBuffer->iData); + buffer->Delete(0, iVolLength); + } + } + + else if ( iCodecType == EH264 ) + { + + TPtr8* ptr = reinterpret_cast(&newBuffer->iData); + TPtr8& buffer(*ptr); + + // Offset to the end + TInt readOffset = buffer.Length(); + readOffset -= 4; + + TInt numNALUnits = 0; + TInt writeOffset = 0; + TInt firstFrameStart = 0; + TInt alignmentBytes = 0; + + numNALUnits = TInt(buffer[readOffset]) + + (TInt(buffer[readOffset + 1]) << 8 ) + + (TInt(buffer[readOffset + 2]) << 16) + + (TInt(buffer[readOffset + 3]) << 24); + + // figure out the payload length of all NAL's to + // determine the number of alignment bytes + + // point to first length field + readOffset -= (numNALUnits - 1) * 8; + readOffset -= 4; + + TInt allNALsLength = 0; + + for (TInt i = 0; i < numNALUnits; i++) + { + TInt len = TInt(buffer[readOffset]) + + (TInt(buffer[readOffset + 1]) << 8) + + (TInt(buffer[readOffset + 2]) << 16) + + (TInt(buffer[readOffset + 3]) << 24); + + allNALsLength += len; + readOffset += 8; + } + + // calculate alignment bytes + alignmentBytes = (allNALsLength % 4 != 0) * ( 4 - (allNALsLength % 4) ); + + // get pointer to end of last frame + writeOffset = buffer.Length() - 4 - numNALUnits * 8; + + // get number of frame NAL's + numNALUnits -= iNumH264SPSPPS; + + // point to offset field of first frame + readOffset = buffer.Length(); + readOffset -= 4; + readOffset -= numNALUnits * 8; + + firstFrameStart = TInt(buffer[readOffset]) + + (TInt(buffer[readOffset + 1]) << 8) + + (TInt(buffer[readOffset + 2]) << 16) + + (TInt(buffer[readOffset + 3]) << 24); + + // The buffer should have enough space for the new NAL header + // if ( frameStart + frameSize + 12 < buffer.Length() ) + + // point to length field of first frame + readOffset += 4; + + // first frame begins from offset 0 + TInt nalOffset = 0; + TInt totalLength = 0; + + for (TInt i = 0; i < numNALUnits; i++) + { + + // read NAL length + TInt length = TInt(buffer[readOffset]) + + (TInt(buffer[readOffset + 1]) << 8) + + (TInt(buffer[readOffset + 2]) << 16) + + (TInt(buffer[readOffset + 3]) << 24); + + totalLength += length; + + // write offset + buffer[writeOffset + 0] = TUint8(nalOffset & 0xff); + buffer[writeOffset + 1] = TUint8((nalOffset >> 8) & 0xff); + buffer[writeOffset + 2] = TUint8((nalOffset >> 16) & 0xff); + buffer[writeOffset + 3] = TUint8((nalOffset >> 24) & 0xff); + + // Write NAL length + writeOffset +=4; + buffer[writeOffset + 0] = TUint8(length & 0xff); + buffer[writeOffset + 1] = TUint8((length >> 8) & 0xff); + buffer[writeOffset + 2] = TUint8((length >> 16) & 0xff); + buffer[writeOffset + 3] = TUint8((length >> 24) & 0xff); + + writeOffset += 4; + readOffset += 8; + + nalOffset += length; + } + + // Write the number of NAL units + buffer[writeOffset + 0] = TUint8(numNALUnits & 0xff); + buffer[writeOffset + 1] = TUint8((numNALUnits >> 8) & 0xff); + buffer[writeOffset + 2] = TUint8((numNALUnits >> 16) & 0xff); + buffer[writeOffset + 3] = TUint8((numNALUnits >> 24) & 0xff); + + // Get a pointer to the position where the frame starts + TPtrC8 tmp(buffer.Ptr() + firstFrameStart, totalLength + alignmentBytes + numNALUnits * 8 + 4); + + // Set output media buffer + iOutputMediaBuffer->Set( tmp, static_cast(iBufferType), + tmp.Length(), newBuffer->iRandomAccessPoint, + newBuffer->iCaptureTimestamp ); + + outputMediaBufferSet = ETrue; + + } + } + + if (!outputMediaBufferSet) + { + iOutputMediaBuffer->Set( newBuffer->iData, static_cast(iBufferType), + newBuffer->iData.Length(), newBuffer->iRandomAccessPoint, + newBuffer->iCaptureTimestamp ); + } + + iObserver.MtrdvcoNewBuffer(iOutputMediaBuffer); + + // Return buffer to devvideo here, since observer call is synchronous + iDevVideoRecord->ReturnBuffer(newBuffer); + } + else + { + PRINT((_L("CTRVideoEncoderClient::MdvroNewBuffers(), newBuffer is not available, nothing to do"))) + break; + } + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::StopL +// Stops encoding synchronously +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::StopL() + { + PRINT((_L("CTRVideoEncoderClient::StopL(), In"))) + + if (iFatalError == KErrNone) + { + iDevVideoRecord->Stop(); + } + + // Reset flags here + iVolHeaderSent = EFalse; + iState = ETRStopped; + + PRINT((_L("CTRVideoEncoderClient::StopL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::AsyncStopL +// Stops encoding asynchronoulsy +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::AsyncStopL() + { + PRINT((_L("CTRVideoEncoderClient::StopL(), Async In"))) + + if (iFatalError == KErrNone) + { + iDevVideoRecord->InputEnd(); + } + + // Reset flags here + iVolHeaderSent = EFalse; + iState = ETRStopping; + + PRINT((_L("CTRVideoEncoderClient::StopL(), Async Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroStreamEnd +// End of stream is reached +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroStreamEnd() + { + PRINT((_L("CTRVideoEncoderClient::MdvpoStreamEnd()"))) + iState = ETRStopped; + iObserver.MtrdvcoEncStreamEnd(); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroSupplementalInfoSent +// Signals that the supplemental info send request has completed. The buffer used for supplemental information can be re-used or freed. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroSupplementalInfoSent() + { + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MdvroFatalError +// Reports the fatal error +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MdvroFatalError(TInt aError) + { + PRINT((_L("CTRVideoEncoderClient::MdvroFatalError(), error[%d]"), aError)) + iFatalError = aError; + iObserver.MtrdvcoFatalError(iFatalError); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::GetCodingStandardSpecificInitOutputLC +// Requests video encoder codinc options +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +HBufC8* CTRVideoEncoderClient::GetCodingStandardSpecificInitOutputLC() + { + if ( iDevVideoRecord ) + { + HBufC8* condigDecInfo = iDevVideoRecord->CodingStandardSpecificInitOutputLC(); + + if (condigDecInfo) + { + PRINT((_L("CTRVideoEncoderClient::GetCodingStandardSpecificInitOutputLC(), Vol header length[%d]"), condigDecInfo->Length())) + + if ( (condigDecInfo->Length() > 0) && (condigDecInfo->Length() <= KMaxDesC8Length /*256*/) ) + { + iVolHeader.Des().Copy( condigDecInfo->Des() ); + + // Keep vol length for further use + iVolLength = iVolHeader.Des().Length(); + PRINT((_L("CTRVideoEncoderClient::GetCodingStandardSpecificInitOutputLC(), VolLength[%d]"), iVolLength)) + + // VOS+VO+VOL header is now going to be stored to metadata, it must not be included in mediadata so remove it from the next buffer + iRemoveHeader = ETrue; + iVolHeaderSent = ETrue; + + if ( iCodecType == EH264 ) + { + TPtr8 temp = condigDecInfo->Des(); + + // get number of SPS/PPS units to be able to + // remove them later from a frame buffer + TInt index = condigDecInfo->Length() - 4; + + iNumH264SPSPPS = TInt(temp[index]) + + (TInt(temp[index + 1]) << 8 ) + + (TInt(temp[index + 2]) << 16) + + (TInt(temp[index + 3]) << 24); + + } + + // Return codingInfo to the client + return condigDecInfo; + } + } + } + + // If condigDecInfo is not valid or something is going wrong, return NULL + return NULL; + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::UseDataTransferOptimization +// Client's request to use optimized data transfer via CI +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::UseDataTransferOptimizationL() + { + PRINT((_L("CTRVideoEncoderClient::UseDataTransferOptimizationL(), In"))) + + // Check buffer management custom interface support before initializing + iVideoBufferManagementCI = (MMmfVideoBufferManagement*)iDevVideoRecord->CustomInterface( iHwDeviceId, KMmfVideoBuffermanagementUid ); + PRINT((_L("CTRVideoEncoderClient::UseDataTransferOptimizationL(), iVideoBufferManagementCI[0x%x]"), iVideoBufferManagementCI)) + + if (iVideoBufferManagementCI) + { + iVideoBufferManagementCI->MmvbmSetObserver(this); + iVideoBufferManagementCI->MmvbmEnable(ETrue); + + // Set buffer options for this mode + MMmfVideoBufferManagement::TBufferOptions bufferOptionsCI; + bufferOptionsCI.iNumInputBuffers = KTRPictureBuffersNumberBMCI; + bufferOptionsCI.iBufferSize = iPictureSize; + iVideoBufferManagementCI->MmvbmSetBufferOptionsL(bufferOptionsCI); + } + else + { + PRINT((_L("CTRVideoEncoderClient::UseDataTransferOptimizationL(), Optimized data transfer is not supported for this hwdevice"))) + User::Leave(KErrNotSupported); + } + + PRINT((_L("CTRVideoEncoderClient::UseDataTransferOptimizationL(), Out"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MmvbmoNewBuffers +// One or several buffers are available throug CI +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MmvbmoNewBuffers() + { + PRINT((_L("CTRVideoEncoderClient::MmvbmoNewBuffers()"))) + + if (iVideoBufferManagementCI) + { + // Call CI observer to the client only in case, if CI was successfully initialized + iObserver.MtrdvcoNewBuffers(); + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MmvbmoReleaseBuffers +// Release buffers +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MmvbmoReleaseBuffers() + { + PRINT((_L("CTRVideoEncoderClient::MmvbmoReleaseBuffers()"))) + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::GetTargetVideoPictureL +// Gets target video picture buffer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TVideoPicture* CTRVideoEncoderClient::GetTargetVideoPictureL() + { + if (iVideoBufferManagementCI) + { + return iVideoBufferManagementCI->MmvbmGetBufferL(iPictureSize); + } + else + { + PRINT((_L("CTRVideoEncoderClient::GetTargetVideoPictureL(), optimized data transfer is not supported"))) + User::Leave(KErrNotSupported); + + // Make compiler happy + return NULL; + } + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::SetRandomAccessPoint +// Requests to set random access point to bitstream +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::SetRandomAccessPoint() + { + PRINT((_L("CTRVideoEncoderClient::SetRandomAccessPoint(), In"))) + + // There are several ways to requestI-Frame: + // 1. Pause() and immediately resume() should force to encoder to generate I-Frame. + // 2. Set TVideoPictureOption: some of encoders don't support this + // 3. PictureLoss(): some of encoders don't support this + + // Use TVideoPictureOption to request the I-frame later + iSetRandomAccessPoint = ETrue; + + PRINT((_L("CTRVideoEncoderClient::SetRandomAccessPoint(), Out"))) + } + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::EstimateEncodeFrameTimeL +// Returns a time estimate on long it takes to encode one frame +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TReal CTRVideoEncoderClient::EstimateEncodeFrameTimeL(const TTRVideoFormat& aOutput, TInt aCodecType) + { + if (iUid == TUid::Null()) + { + PRINT((_L("CTRVideoEncoderClient::EstimateEncodeFrameTimeL(), no encoder selected yet"))) + User::Leave(KErrNotReady); + } + + TReal time = 0.0; + + // Select the predefined constant using the current settings + if (aCodecType == EH263) + { + time = iAcceleratedCodecSelected ? KTREncodeTimeFactorH263HW : KTREncodeTimeFactorH263SW; + } + else if (aCodecType == EH264) + { + time = iAcceleratedCodecSelected ? KTREncodeTimeFactorH264HW : KTREncodeTimeFactorH264SW; + } + else + { + time = iAcceleratedCodecSelected ? KTREncodeTimeFactorMPEG4HW : KTREncodeTimeFactorMPEG4SW; + } + + // Multiply the time by the resolution of the output frame + time *= static_cast(aOutput.iSize.iWidth + aOutput.iSize.iHeight) * KTRTimeFactorScale; + + PRINT((_L("CTRVideoEncoderClient::EstimateEncodeFrameTimeL(), encode frame time: %.2f"), time)) + + return time; + } + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::Pause +// Pauses encoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::Pause() + { + if ((iFatalError == KErrNone) && (iState == ETRRunning)) + { + iDevVideoRecord->Pause(); + iState = ETRPaused; + } + } + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::Resume +// Resumes encoding +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::Resume() + { + if ((iFatalError == KErrNone) && (iState == ETRPaused)) + { + iDevVideoRecord->Resume(); + iState = ETRRunning; + } + } + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::EnableResourceObserver +// Enable / Disable resourece observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::EnableResourceObserver(TBool aEnable) + { + PRINT((_L("CTRVideoEncoderClient::EnableResourceObserver(), In"))) + + iVideoResourceHandlerCI = (MMmfVideoResourceHandler*)iDevVideoRecord->CustomInterface( iHwDeviceId, KUidMmfVideoResourceManagement ); + PRINT((_L("CTRVideoEncoderClient::EnableResourceObserver(), iVideoResourceHandlerCI[0x%x]"), iVideoResourceHandlerCI)) + + if (iVideoResourceHandlerCI) + { + if (aEnable) + { + iVideoResourceHandlerCI->MmvrhSetObserver(this); + PRINT((_L("CTRVideoEncoderClient::EnableResourceObserver(), Enabled"))) + } + else + { + iVideoResourceHandlerCI->MmvrhSetObserver(NULL); + } + } + + PRINT((_L("CTRVideoEncoderClient::EnableResourceObserver(), Out"))) + } + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MmvroResourcesLost +// Indicates that a media device has lost its resources +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MmvroResourcesLost(TUid /*aMediaDevice*/) + { + iObserver.MtrdvcoResourcesLost(EFalse); + } + + +// ----------------------------------------------------------------------------- +// CTRVideoEncoderClient::MmvroResourcesRestored +// Indicates that a media device has regained its resources +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CTRVideoEncoderClient::MmvroResourcesRestored(TUid /*aMediaDevice*/) + { + iObserver.MtrdvcoResourcesRestored(); + } + +// End of file +