--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/h264_enc/arih264enchwdevice/src/arih264enchwdeviceimpl.cpp Fri Jul 23 16:58:44 2010 +0100
@@ -0,0 +1,4779 @@
+/*
+* Copyright (c) 2009 Aricent and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:
+* Aricent - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Implementation of member functions of H264 encoder plugin class -
+* CAriH264encHwDeviceImpl.
+*
+*/
+
+// System Includes
+#include <e32base.h>
+#include <avc.h>
+#include <e32math.h>
+
+// User Includes
+#include "arih264enchwdeviceimpl.h"
+#include "arih264hwdeviceconstants.h"
+#include "arih264encwrapper.h"
+
+
+
+// MACRO DEFINITIONS - start
+
+// Uncomment this flag to enable instant rate calculations on-the-fly in urel
+// builds. In UDEB it is enabled automatically
+// By default it is commented
+//#define CALCINSTANTBITRATE
+
+// Uncomment to print additional debug information retrieved from
+// core encoder
+//#define DEBUG_INFO
+
+// MACRO DEFINITIONS - end
+
+//----------------------------------------------------------------------------
+// Maps the num/denom from the MDF to the aspect_ratio_idc value supported
+//----------------------------------------------------------------------------
+//
+TInt32 MapAspectRatio( TUint32 aNumerator, TUint32 aDenominator )
+ {
+ PRINT_ENTRY;
+ TInt32 aspectratio = -1;
+ switch ( aDenominator )
+ {
+ case 1:
+ if ( aNumerator == 1 )
+ {
+ aspectratio = 1;
+ }
+ break;
+ case 11:
+ switch ( aNumerator )
+ {
+ case 12:
+ aspectratio = 2;
+ break;
+ case 10:
+ aspectratio = 3;
+ break;
+ case 16:
+ aspectratio = 4;
+ break;
+ case 24:
+ aspectratio = 6;
+ break;
+ case 20:
+ aspectratio = 7;
+ break;
+ case 32:
+ aspectratio = 8;
+ break;
+ case 18:
+ aspectratio = 10;
+ break;
+ case 15:
+ aspectratio = 11;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 33:
+ switch ( aNumerator )
+ {
+ case 40:
+ aspectratio = 5;
+ break;
+ case 80:
+ aspectratio = 9;
+ break;
+ case 64:
+ aspectratio = 12;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 99:
+ if ( aNumerator == 160 )
+ {
+ aspectratio = 13;
+ }
+
+ break;
+ default:
+ break;
+ }
+ PRINT_EXIT;
+ return aspectratio;
+ }
+
+//----------------------------------------------------------------------------
+// Two phase constructor for an object of CAriH264encHwDeviceImpl
+//----------------------------------------------------------------------------
+//
+CAriH264encHwDeviceImpl* CAriH264encHwDeviceImpl::NewL()
+ {
+ PRINT_ENTRY;
+ CAriH264encHwDeviceImpl* self = new ( ELeave ) CAriH264encHwDeviceImpl();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ PRINT_EXIT;
+ return self;
+ }
+
+//----------------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------------
+//
+CAriH264encHwDeviceImpl::CAriH264encHwDeviceImpl()
+ :iMMFDevVideoRecordProxy( NULL ),
+ iInputDevice ( NULL ),
+ iClockSource ( NULL ),
+ iInputBufReturnToPreProc( EFalse ),
+ iPeriodicTimer ( NULL ),
+ iClockTimeWhenPaused( 0 ),
+ //100 milli seconds
+ iPollingInterval(TTimeIntervalMicroSeconds32( KPOLLINGINTERVAL ) ),
+ iCodec( NULL ),
+ iEngine( NULL ),
+ iOutputBuffers( NULL ),
+ iOutputBufferSize( 0 ),
+ iPauseOffset( 0 ),
+ iTotalTime( 0 ),
+ iLastEncodedPictureTimestamp( 0 ),
+ iPictureLoss( EFalse ),
+ iInputEndCalled( EFalse ),
+ iFrozen( EFalse ),
+ iTotalLengthFilledSoFarInPacketMode( 0 ),
+ iTotalOutputBufferLengthInPacketMode( 0 ),
+ iPacketOffSetCurrentPosition( NULL ),
+ iPacketOffSetAndLengthInfoBuffers( NULL ),
+ iInternalOutputBuffers( NULL ),
+ iNumOfBuffersAtClientInPacketModeNeedReAllocation( 0 ),
+ iPacketsPending( EFalse ),
+ iNumOfOutBuffersAvailableInPacketModeChange( 0 ),
+ iNumofBuffersPendingFromClientInChangeToPacketMode( 0 ),
+ iNumOfOutBuffersBeforeChangeToPacketMode( 0 ),
+ iCodedBufferForPacketModeChange( NULL ),
+ iSegmentBuffers( NULL ),
+ iIsConfigDataFilledInFirstOutputBuffer( EFalse ),
+ iIsSliceEnabledInCodedPicture( EFalse ),
+ iNoOfOutputFramesPerSec( 0 ),
+ iSizePerFrame( 0 ),
+ iEncStateMac( NULL )
+ {
+ PRINT_ENTRY;
+
+ iSupportedDataUnitTypes = EDuCodedPicture | EDuVideoSegment;
+
+ iSupportedDataUnitEncapsulations = EDuElementaryStream
+ | EDuGenericPayload;
+
+ // Default values for Init params - full range
+ TUncompressedVideoFormat inputFormat;
+ inputFormat.iDataFormat = EYuvRawData;
+ inputFormat.iYuvFormat.iCoefficients = EYuvBt709Range1;
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma1;
+ inputFormat.iYuvFormat.iDataLayout = EYuvDataPlanar;
+ inputFormat.iYuvFormat.iYuv2RgbMatrix = NULL;
+ inputFormat.iYuvFormat.iRgb2YuvMatrix = NULL;
+ inputFormat.iYuvFormat.iAspectRatioNum = 1;
+ inputFormat.iYuvFormat.iAspectRatioDenom = 1;
+
+ iH264EncInitParams.iInputFormat = inputFormat;
+
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_UNKNOWN;
+
+ iH264EncInitParams.iAfterInitialize = 0;
+
+ iH264EncInitParams.iOutputFormat = EH264;
+
+ iH264EncInitParams.iMinNumOutputBuffers
+ = KH264ENCIMPL_MAXNUM_OUTPUTBUFFERS;
+
+ iH264EncInitParams.iMaxCodedSegmentSize
+ = KH264ENCIMPL_DEFAULT_SEGMENTSIZE;
+
+ iH264EncInitParams.iMaxPictureRate = KH264ENCIMPL_DEFAULT_PICTURERATE;
+
+ // initialize picture counters
+ iPictureCounters.iPicturesSkippedBufferOverflow = 0;
+ iPictureCounters.iPicturesSkippedProcPower = 0;
+ iPictureCounters.iPicturesSkippedRateControl = 0;
+ iPictureCounters.iPicturesProcessed = 0;
+ iPictureCounters.iInputPictures = 0;
+
+ // default packet mode is off
+ iH264EncInitParams.iDataEncapsulation = EDuElementaryStream;
+
+ iH264EncInitParams.iDataUnitType = EDuCodedPicture;
+
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_DEFAULT_BITRATE;
+ iH264EncInitParams.iTargetPictureRate = KH264ENCIMPL_DEFAULT_PICTURERATE;
+ iH264EncInitParams.iRandomAccessRate
+ = KH264ENCIMPL_DEFAULT_RANDOMACCESSRATE;
+
+ PRINT_EXIT;
+
+ }
+
+//----------------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------------
+//
+CAriH264encHwDeviceImpl::~CAriH264encHwDeviceImpl()
+ {
+ PRINT_ENTRY;
+ PRINT_MSG( LEVEL_LOW, ( "this is %x", this ) );
+
+ iSupportedInputFormats.Close();
+
+ iLevels.Close();
+
+ //allocated formats should be deleted before closing
+ while ( iSupportedOutputFormats.Count() > 0 )
+ {
+ CCompressedVideoFormat* lCompFormat = iSupportedOutputFormats[0];
+ iSupportedOutputFormats.Remove( 0 );
+ delete lCompFormat;
+ }
+
+ iSupportedOutputFormats.Close();
+
+ // Stop processing
+ if( !iEncStateMac->IsStopped() && ( !iEncStateMac->IsInDeadState() ) )
+ {
+ if( iEncStateMac->IsInitialized() )
+ {
+ Stop();
+ }
+ }
+
+ if( iEngine )
+ {
+ iEngine->Reset();
+ delete iEngine;
+ iEngine = NULL;
+ }
+
+ if( iCodec )
+ {
+ delete iCodec;
+ iCodec = NULL;
+ }
+
+ //delete output buffers
+ iOutputFreeBufferQueue.Reset();
+
+ if( iOutputBuffers )
+ {
+ if( iNumOfOutBuffersBeforeChangeToPacketMode )
+ {
+ for ( TInt i = 0; i < iNumOfOutBuffersBeforeChangeToPacketMode
+ ; i++ )
+ {
+ if ( iOutputBuffers[i].iData.Ptr() )
+ {
+ delete ( TUint8* )iOutputBuffers[i].iData.Ptr();
+ }
+ }
+ }
+ else
+ {
+ for ( TInt i = 0; i < iH264EncInitParams.iMinNumOutputBuffers;
+ i++ )
+ {
+ if ( iOutputBuffers[i].iData.Ptr() )
+ {
+ delete ( TUint8* )iOutputBuffers[i].iData.Ptr();
+ }
+ }
+ }
+ delete []iOutputBuffers;
+ }
+
+ delete iPeriodicTimer;
+ iPeriodicTimer = NULL;
+
+ if ( iPacketOffSetAndLengthInfoBuffers )
+ {
+ for( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ delete [] ( TUint8* )iPacketOffSetAndLengthInfoBuffers[i];
+ }
+ delete []( TUint* )iPacketOffSetAndLengthInfoBuffers;
+ }
+
+ //delete temp output buffers
+ iInternalOutputBufferQueue.Reset();
+
+ if( iInternalOutputBuffers )
+ {
+ for ( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ if ( iInternalOutputBuffers[i].iData.Ptr() )
+ {
+ delete ( TUint8* )iInternalOutputBuffers[i].iData.Ptr();
+ }
+ }
+ delete []iInternalOutputBuffers;
+ }
+
+ if ( iCodedBufferForPacketModeChange )
+ {
+ if ( iCodedBufferForPacketModeChange->iData.Ptr() )
+ {
+ delete iCodedBufferForPacketModeChange->iData.Ptr();
+ }
+
+ delete iCodedBufferForPacketModeChange;
+ }
+
+ iFreeBufferQueueForPacketOffsetInfo.Reset();
+ iFilledBufferQueueForPacketOffsetInfo.Reset();
+
+ //delete the segment buffers
+ if( iSegmentBuffers )
+ {
+ for ( TInt i = 0; i < iH264EncInitParams.iMinNumOutputBuffers; i++ )
+ {
+ if ( iSegmentBuffers[i].iData.Ptr() )
+ {
+ delete ( TUint8* )iSegmentBuffers[i].iData.Ptr();
+ }
+ }
+ delete []iSegmentBuffers;
+ }
+
+ if ( iConfigData )
+ {
+ delete iConfigData;
+ iConfigData = NULL;
+ }
+
+ if ( iEncStateMac )
+ {
+ delete iEncStateMac;
+ iEncStateMac = NULL;
+ }
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Custom Interface supported by the HwDevice plugin
+//----------------------------------------------------------------------------
+//
+TAny* CAriH264encHwDeviceImpl::CustomInterface( TUid aInterface )
+ {
+ PRINT_ENTRY;
+ if( aInterface == KH324AnnexKDefinedEncoderConfigDataCIUid )
+ {
+ PRINT_EXIT;
+ return ( ( MH324AnnexKDefinedEncoderConfigDataCI* ) this );
+ }
+ else
+ {
+ PRINT_EXIT;
+ return NULL;
+ }
+ }
+
+//----------------------------------------------------------------------------
+// Returns information about this Encoder HW Device
+//----------------------------------------------------------------------------
+//
+CVideoEncoderInfo* CAriH264encHwDeviceImpl::VideoEncoderInfoLC()
+ {
+ PRINT_ENTRY;
+
+ TSize maxPictureSize = TSize( KH264ENCIMPL_SDTV_WIDTH,
+ KH264ENCIMPL_SDTV_HEIGHT_PAL );
+
+ TUint32 maxBitRate = KMAXSUPPBITRATE;
+ RArray<TPictureRateAndSize> maxPictureRatesAndSizes;
+ CleanupClosePushL( maxPictureRatesAndSizes );
+
+ TPictureRateAndSize pictureRateAndSize;
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_QCIF_WIDTH,
+ KH264ENCIMPL_QCIF_HEIGHT );
+
+ TInt error = KErrNone;
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_VGA_WIDTH,
+ KH264ENCIMPL_VGA_HEIGHT );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_CIF_WIDTH,
+ KH264ENCIMPL_CIF_HEIGHT );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_SQCIF_WIDTH,
+ KH264ENCIMPL_SQCIF_HEIGHT );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_QVGA_WIDTH,
+ KH264ENCIMPL_QVGA_HEIGHT );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_SDTV_WIDTH,
+ KH264ENCIMPL_HALFSDTV_HEIGHT_NTSC);
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_SDTV_WIDTH,
+ KH264ENCIMPL_HALFSDTV_HEIGHT_PAL );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KPictureRate30;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_SDTV_WIDTH,
+ KH264ENCIMPL_SDTV_HEIGHT_NTSC );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ pictureRateAndSize.iPictureRate = KH264ENCIMPL_PICTURERATE_25;
+ pictureRateAndSize.iPictureSize = TSize( KH264ENCIMPL_SDTV_WIDTH,
+ KH264ENCIMPL_SDTV_HEIGHT_PAL );
+
+ error = maxPictureRatesAndSizes.Append( pictureRateAndSize );
+
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending maximum picture rate and size" );
+ User::Leave( error );
+ }
+
+ TUint32 supportedPictureOptions = TVideoPicture::ETimestamp |
+ TVideoPicture::EReqInstantRefresh;
+
+ TUint32 supportedDataUnitEncapsulations = EDuElementaryStream |
+ EDuGenericPayload;
+
+ TUint32 supportedDataUnitTypes = EDuCodedPicture |
+ EDuVideoSegment;
+
+ CVideoEncoderInfo* lVideoEncoderInfo = CVideoEncoderInfo::NewL( TUid::
+ Uid( KUidH264EncoderHwDeviceImplUid ),
+ KH264EncManufacturer,
+ KH264EncIdentifier,
+ TVersion( KH264ENCIMPL_MAJOR_VERSION,
+ KH264ENCIMPL_MINOR_VERSION,
+ KH264ENCIMPL_BUILD_VERSION ),
+ // Accelerated
+ EFalse,
+ // Enc doesnt support direct capture
+ EFalse,
+ iSupportedInputFormats.Array(),
+ iSupportedOutputFormats.Array(),
+ maxPictureSize,
+ supportedDataUnitTypes,
+ supportedDataUnitEncapsulations,
+ // Max bitrate layers
+ 1,
+ //aSupportsSupplementalEnhancementInfo
+ EFalse,
+ //aMaxUnequalErrorProtectionLevels
+ 1,
+ maxBitRate,
+ maxPictureRatesAndSizes.Array(),
+ //aMaxInLayerScalabilitySteps
+ 1,
+ supportedPictureOptions,
+ //aSupportsPictureLoss
+ ETrue,
+ //aSupportsSliceLoss
+ ETrue,
+ //aCodingStandardSpecificInfo
+ KNullDesC8,
+ //aImplementationSpecificInfo
+ KNullDesC8 );
+
+ CleanupStack::PopAndDestroy();
+ CleanupStack::PushL( lVideoEncoderInfo );
+
+ PRINT_EXIT;
+ return lVideoEncoderInfo;
+ }
+
+
+//----------------------------------------------------------------------------
+// Sets the encoder output format
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetOutputFormatL(
+ const CCompressedVideoFormat& aFormat,
+ TVideoDataUnitType aDataUnitType,
+ TVideoDataUnitEncapsulation aDataEncapsulation,
+ TBool aSegmentationAllowed )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetOutputFormatL () called before Initialize ()" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ TInt error = KErrNotFound;
+
+ TPtrC8 mimeType( aFormat.MimeType() );
+
+ // Check if format is supported else return KErrNotSupported
+ for ( TInt i = 0; i < iSupportedOutputFormats.Count(); i++ )
+ {
+ CCompressedVideoFormat* lFormat = iSupportedOutputFormats[i];
+
+ if( mimeType.CompareF( lFormat->MimeType() ) == 0 )
+ {
+ iH264EncInitParams.iLevel = iLevels[i];
+ error = KErrNone;
+ break;
+ }
+ }
+
+ if( error == KErrNotFound )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl::SetOutputFormatL() Leaving"
+ " because of unsupported output mimetype" );
+
+ User::Leave( KErrNotSupported );
+ return;
+ }
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetOutputFormatL() "
+ "level is set to %d", (TInt)iH264EncInitParams.iLevel ) );
+
+ if ( ( ( aDataUnitType != EDuCodedPicture ) &&
+ ( aDataUnitType != EDuVideoSegment ) ) ||
+ ( ( aDataEncapsulation != EDuElementaryStream ) &&
+ ( aDataEncapsulation != EDuGenericPayload ) ) ||
+ ( ( aSegmentationAllowed ) ) )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl::SetOutputFormatL() Leaving"
+ " because of unsupported data unit type or data unit"
+ " encapsulation" );
+ User::Leave( KErrNotSupported );
+ }
+
+ if( aDataUnitType == EDuCodedPicture )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetOutputFormatL() "
+ "Packet mode is OFF" ) );
+ }
+ else
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetOutputFormatL() "
+ "Packet mode is ON" ) );
+ // must be calculated from and levels set by the client
+ iH264EncInitParams.iMinNumOutputBuffers
+ = KH264ENCIMPL_MAXNUM_SEGMENTBUFFERS;
+ }
+
+ iH264EncInitParams.iDataUnitType = aDataUnitType;
+ iH264EncInitParams.iDataEncapsulation = aDataEncapsulation;
+ iH264EncInitParams.iSegmentationAllowed = aSegmentationAllowed;
+ iH264EncInitParams.iBeforeInitialize |= EEncOutputFormat;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the pre-processor device that will write data to this encoder
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetInputDevice(
+ CMMFVideoPreProcHwDevice* aDevice )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError ( KErrPermissionDenied );
+ return;
+ }
+
+ if( !aDevice )
+ {
+ ClientFatalError ( KErrArgument );
+ return;
+ }
+
+ iInputDevice = aDevice;
+ iH264EncInitParams.iBeforeInitialize |= EEncInputDevice;
+ iInputBufReturnToPreProc = ETrue;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the number of bit-rate scalability layers to use
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetNumBitrateLayersL( TUint aNumLayers )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetNumBitrateLayersL () called before Initialize"
+ "..leaving" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ if( aNumLayers != 1 )
+ {
+ PRINT_ERR( "Wrong value passed for aNumLayers... Leaving" );
+ User::Leave( KErrNotSupported );
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the scalability type for a bit-rate scalability layer. Currently not
+// supported.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetScalabilityLayerTypeL(
+ TUint /*aLayer*/,
+ TScalabilityType /*aScalabilityType*/ )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetScalabilityLayerTypeL() called before Initialize"
+ "..leaving" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ PRINT_ERR( "SetScalabilityLayerTypeL() not supported...Leaving with "
+ "KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Sets the reference picture options to be used for all scalability layers
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetGlobalReferenceOptions(
+ TUint aMaxReferencePictures,
+ TUint aMaxPictureOrderDelay )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ if( aMaxPictureOrderDelay != 0 || aMaxReferencePictures
+ > KH264ENCIMPL_MAXNUM_REFERENCEPICTURES )
+ {
+ ClientFatalError( KErrNotSupported );
+ return;
+ }
+
+ iH264EncInitParams.iLayerReferenceOptions[0].iMaxReferencePictures
+ = aMaxReferencePictures;
+
+ iH264EncInitParams.iLayerReferenceOptions[0].iMaxPictureOrderDelay
+ = aMaxPictureOrderDelay;
+
+ iH264EncInitParams.iBeforeInitialize |= EEncGlobalRefOptions;
+
+ PRINT_EXIT
+ }
+
+//----------------------------------------------------------------------------
+// Sets the reference picture options to be used for a single scalability
+// layer
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetLayerReferenceOptions( TUint /*aLayer*/,
+ TUint /*aMaxReferencePictures*/,
+ TUint /*aMaxPictureOrderDelay*/ )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+ ClientFatalError( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+///---------------------------------------------------------------------------
+// Sets encoder buffering options
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetBufferOptionsL(
+ const TEncoderBufferOptions& aOptions )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetBufferOptionsL () called before Initialize ()" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iMaxPreEncoderBufferPictures = %d" ,
+ (TInt)aOptions.iMaxPreEncoderBufferPictures ) );
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iMaxOutputBufferSize = %d",
+ ( TInt ) aOptions.iMaxOutputBufferSize ) );
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iMaxCodedPictureSize = %d" ,
+ ( TInt )aOptions.iMaxCodedPictureSize ) );
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iHrdVbvSpec = %x", ( TInt ) aOptions.iHrdVbvSpec ) );
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iMinNumOutputBuffers = %d" ,
+ ( TInt ) aOptions.iMinNumOutputBuffers ) );
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetBufferOptionsL() "
+ "iMaxCodedSegmentSize = %d" ,
+ ( TInt ) aOptions.iMaxCodedSegmentSize ) );
+
+ if( ( aOptions.iMaxPreEncoderBufferPictures == 0 ) ||
+ ( aOptions.iMaxOutputBufferSize == 0 ) ||
+ ( aOptions.iMinNumOutputBuffers == 0 ) ||
+ ( aOptions.iHrdVbvSpec == EHrdVbv3GPP ) )
+ {
+ PRINT_ERR( "SetBufferOptionsL () - incorrect parameter passed ..."
+ "leaving with KErrNotSupported" );
+ User::Leave ( KErrNotSupported );
+ return;
+ }
+
+ if ( aOptions.iHrdVbvParams != KNullDesC8 )
+ {
+ if ( aOptions.iHrdVbvSpec == EHrdVbvNone )
+ {
+ PRINT_ERR( "SetBufferOptionsL () - incorrect HrdVbvParams or"
+ "iHrdVbvSpec passed ...leaving with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+ return;
+ }
+
+ TPckgBuf <TAvcPictureHeader> params;
+ params.Copy ( aOptions.iHrdVbvParams );
+ TUint size = sizeof( TAvcPictureHeader );
+ if ( size != aOptions.iHrdVbvParams.Length() )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl::SetBufferOptionsL() -"
+ "invalid structure passed for iHrdVbvParams" );
+ User::Leave( KErrArgument );
+ }
+
+ // Perform the checks on the members of
+ if( ( params().iBaselineProfileConstraintSet == ( TBool )EFalse ) ||
+ ( params().iMainProfileConstraintSet == ( TBool )ETrue ) ||
+ ( params().iExtendedProfileConstraintSet == ( TBool )ETrue ) ||
+ ( ( params().iPictureType ) & EAvcPictureTypeB ) ||
+ ( ( params().iPictureType ) & EAvcPictureTypeSI ) ||
+ ( ( params().iPictureType ) & EAvcPictureTypeSP ) ||
+ ( params().iLongTermPicture == ( TBool )ETrue ) ||
+ ( params().iFrame == ( TBool )EFalse ) ||
+ ( params().iQPY < 10 ) ||
+ ( params().iQPY > 51 ) )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl ::SetBufferOptionsL Invalid "
+ "data passed in TAVCHrdParams" );
+ User::Leave( KErrNotSupported );
+ return;
+ }
+ }
+
+ iH264EncInitParams.iMaxPreEncoderBufferPictures
+ = aOptions.iMaxPreEncoderBufferPictures;
+
+ iH264EncInitParams.iMaxOutputBufferSize = aOptions.iMaxOutputBufferSize;
+ iH264EncInitParams.iMaxCodedPictureSize = aOptions.iMaxCodedPictureSize;
+ iH264EncInitParams.iMaxCodedSegmentSize = aOptions.iMaxCodedSegmentSize;
+ iH264EncInitParams.iMinNumOutputBuffers = aOptions.iMinNumOutputBuffers;
+ iH264EncInitParams.iBeforeInitialize |= EEncBufferOptions;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the encoder output rectangle
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetOutputRectL( const TRect& aRect )
+ {
+ PRINT_ENTRY;
+
+ if( ( aRect.iTl.iX >= aRect.iBr.iX ) ||
+ ( aRect.iTl.iY >= aRect.iBr.iY ) )
+ {
+ PRINT_ERR( " Invalid parameteres passed..Leaving " );
+ User::Leave ( KErrNotSupported );
+ return;
+ }
+
+ iH264EncInitParams.iOutputRect = aRect;
+ iH264EncInitParams.iBeforeInitialize |= EEncOutputRectSize;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets whether bit errors or packets losses can be expected in the video
+// transmission
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetErrorsExpected( TBool aBitErrors,
+ TBool aPacketLosses )
+ {
+ PRINT_ENTRY;
+
+ // This can bel called before and after initialize
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetErrorsExpected()"
+ " BitErrors is set to [ %d ]", aBitErrors ) );
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::SetErrorsExpected() "
+ "iPacketLosses is set to [ %d ]", aPacketLosses ) );
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ iCurSetH264EncParams.iBitErrors = aBitErrors;
+ iCurSetH264EncParams.iPacketLosses = aPacketLosses;
+ iCurSetH264EncParams.iAfterInitialize |= EEncErrorsExpected;
+ }
+ else
+ {
+ iH264EncInitParams.iBitErrors = aBitErrors;
+ iH264EncInitParams.iPacketLosses = aPacketLosses;
+ iH264EncInitParams.iBeforeInitialize |= EEncErrorsExpected;
+ }
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Sets the minimum frequency (in time) for instantaneous random access points
+// in the bitstream
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetMinRandomAccessRate( TReal aRate )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ // simply return no further action is taken
+ if( aRate <= 0.0 )
+ {
+ return;
+ }
+ iCurSetH264EncParams.iRandomAccessRate = aRate;
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl"
+ "::SetMinRandomAccessRate() iRandomAccessRate is %f" ,
+ ( TReal )iH264EncInitParams.iRandomAccessRate ) );
+
+ iCurSetH264EncParams.iAfterInitialize |= EEncRandomAccessRate;
+ }
+ else
+ {
+ if( aRate <= 0.0 )
+ {
+ ClientFatalError ( KErrNotSupported );
+ return;
+ }
+ iH264EncInitParams.iRandomAccessRate = aRate;
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl"
+ "::SetMinRandomAccessRate() iRandomAccessRate is %f" ,
+ ( TReal )iH264EncInitParams.iRandomAccessRate ) );
+
+ iH264EncInitParams.iBeforeInitialize |= EEncRandomAccessRate;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets coding-standard specific encoder options.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetCodingStandardSpecificOptionsL(
+ const TDesC8& aOptions )
+ {
+ PRINT_ENTRY;
+
+ if ( aOptions == KNullDesC8 )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl"
+ "::SetCodingStandardSpecificOptionsL() Leaving because Null "
+ "Descriptor Passed" );
+ User::Leave( KErrArgument );
+ }
+
+ // validate the parameters
+ TPckgBuf<TAvcVideoMode> avcVideoMode;
+ TUint size = sizeof( TAvcVideoMode );
+ if ( size != aOptions.Length() )
+ {
+ PRINT_MSG( LEVEL_HIGH, ( "CAriH264encHwDeviceImpl"
+ "::SetCodingStandardSpecificOptionsL() - invalid structure passed") );
+ User::Leave( KErrArgument );
+ }
+
+ // before init
+ if( !iEncStateMac->IsInitialized() )
+ {
+ iH264EncInitParams.iCodingStandardSpecificOptions = avcVideoMode();
+ iH264EncInitParams.iBeforeInitialize
+ |= EEncCodingStandardSpecificOptions;
+ }
+ avcVideoMode.Copy( aOptions );
+
+ if ( ( avcVideoMode().iAllowedPictureTypes & EAvcPictureTypeB ) ||
+ ( avcVideoMode().iAllowedPictureTypes & EAvcPictureTypeSI ) ||
+ ( avcVideoMode().iAllowedPictureTypes & EAvcPictureTypeSP ) ||
+ ( avcVideoMode().iFlexibleMacroblockOrder ) ||
+ ( avcVideoMode().iRedundantPictures ) ||
+ ( avcVideoMode().iDataPartitioning ) ||
+ ( !avcVideoMode().iFrameMBsOnly ) ||
+ ( avcVideoMode().iMBAFFCoding ) ||
+ ( avcVideoMode().iEntropyCodingCABAC ) ||
+ ( avcVideoMode().iWeightedPPrediction ) ||
+ ( avcVideoMode().iWeightedBipredicitonMode ) )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl"
+ "::SetCodingStandardSpecificOptionsL() - leaving invalid data "
+ "passed for TAvcVideoMode" );
+ User::Leave( KErrNotSupported );
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets coding-standard specific encoder options.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetImplementationSpecificEncoderOptionsL(
+ const TDesC8& /*aOptions*/)
+ {
+ PRINT_ENTRY;
+
+ //This API can be called at any point of time
+ PRINT_ERR( "SetImplementationSpecificEncoderOptionsL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Returns coding-standard specific initialization output from the encoder
+//----------------------------------------------------------------------------
+//
+HBufC8* CAriH264encHwDeviceImpl::CodingStandardSpecificInitOutputLC()
+ {
+ PRINT_ENTRY;
+
+ TUint configlength;
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "CodingStandardSpecificInitOutputLC () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+ TUint err = iCodec->GetParam( CONTROL_CMD_GET_CONFIG_LENGTH,
+ &configlength );
+ if ( err )
+ {
+ PRINT_ERR("GetParam failure");
+ User::Leave( err );
+ }
+
+ iConfigData = HBufC8::NewL( configlength );
+ err = iCodec->GetParam( CONTROL_CMD_GET_CONFIG_HEADER, iConfigData );
+
+ if ( err )
+ {
+ PRINT_ERR("GetParam failure");
+ User::Leave( err );
+ }
+
+ PRINT_EXIT;
+ return iConfigData;
+ }
+
+//----------------------------------------------------------------------------
+// Returns coding-standard specific initialization output from the encoder
+//----------------------------------------------------------------------------
+//
+HBufC8* CAriH264encHwDeviceImpl::ImplementationSpecificInitOutputLC()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "ImplementationSpecificInitOutputLC () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ return NULL;
+ }
+
+ PRINT_ERR( "ImplementationSpecificInitOutputLC () not supported...leaving"
+ "with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ return NULL;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the number of unequal error protection levels
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetErrorProtectionLevelsL(TUint /*aNumLevels*/,
+ TBool /*aSeparateBuffers*/)
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetErrorProtectionLevelsL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "SetErrorProtectionLevelsL() not supported...leaving"
+ "with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the number of unequal error protection levels
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetErrorProtectionLevelL( TUint /*aLevel*/,
+ TUint /*aBitrate*/,
+ TUint /*aStrength*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetErrorProtectionLevelsL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "SetErrorProtectionLevelsL() not supported...leaving"
+ "with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the expected or prevailing channel conditions for an unequal
+// error protection level, in terms of expected packet loss rate
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetChannelPacketLossRate( TUint /*aLevel*/,
+ TReal /*aLossRate*/,
+ TTimeIntervalMicroSeconds32 /*aLossBurstLength*/ )
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ //packet mode is already enabled
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl"
+ " ::SetChannelPacketLossRate()- already in packet mode returning" ) );
+ return;
+ }
+
+ // Flush the output buffers
+ iEngine->ReturnOutputBuffers();
+
+ // output buffers status
+ iNumOfOutBuffersAvailableInPacketModeChange
+ = iOutputFreeBufferQueue.Count();
+
+ iNumofBuffersPendingFromClientInChangeToPacketMode
+ = iH264EncInitParams.iMinNumOutputBuffers
+ - iOutputFreeBufferQueue.Count();
+
+ iNumOfOutBuffersBeforeChangeToPacketMode
+ = iH264EncInitParams.iMinNumOutputBuffers;
+
+ TInt error = KErrNone;
+ // some buffers are available
+ if ( iNumOfOutBuffersAvailableInPacketModeChange )
+ {
+ while( iOutputFreeBufferQueue.Count() )
+ {
+ // add to engine
+ iEngine->AddOutput( iOutputFreeBufferQueue[0] );
+
+ // remove this buffer
+ iOutputFreeBufferQueue.Remove( 0 );
+ }
+ }
+ else
+ {
+ // create one buffer which can hold one encoded picture
+ TRAP( error, CreateCodedBufferForModeChangeL() );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ }
+
+ iH264EncInitParams.iMaxCodedSegmentSize
+ = KH264ENCIMPL_DEFAULT_SEGMENTSIZE;
+
+ // Get the maximum output buffer size for the encoder
+ TUint maxOutputBufferSize =0;
+ error = iCodec->GetParam( CONTROL_CMD_GET_MAX_FRAME_SIZE,
+ &maxOutputBufferSize );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ iH264EncInitParams.iMinNumOutputBuffers = ( maxOutputBufferSize /
+ iH264EncInitParams.iMaxCodedSegmentSize ) *
+ KH264ENCIMPL_MAXNUM_OUTPUTBUFFERS;
+
+ TRAP( error, CreateSegmentOutputBuffersL (
+ iH264EncInitParams.iMinNumOutputBuffers,
+ iH264EncInitParams.iMaxCodedSegmentSize ) )
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ error = iCodec->GetParam( CONTROL_CMD_GET_MAX_NUM_PACKETS,
+ &iMaxNumOfPackets );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ TRAP( error, CreatePacketOffsetLengthInfoBuffersL( iMaxNumOfPackets ) );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ TBool yesorno = ETrue;
+ error = iCodec->SetParam( CONTROL_CMD_SET_PACKET_MODE, &yesorno );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ // change output mode to videosegment
+ iH264EncInitParams.iDataUnitType = EDuVideoSegment;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the expected or prevailing channel conditions for an unequal error
+// protection level, in terms of expected bit error rate
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetChannelBitErrorRate( TUint /*aLevel*/,
+ TReal aErrorRate, TReal /*aStdDeviation*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ // ignore the negative and 0 error rate values - #AANV-6QSC9N
+ if ( aErrorRate < 0.0 )
+ {
+ return;
+ }
+
+ TReal* bitErrorRate = NULL;
+ TRAPD( error , bitErrorRate = new( ELeave )TReal );
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ *bitErrorRate = aErrorRate;
+ TRAP( error, iEngine->AddCommandL( CBaseEngine::EHighPriority,
+ CONTROL_CMD_SET_CHANNEL_BIT_ERROR_RATE, bitErrorRate ) );
+ if( error != KErrNone )
+ {
+ delete bitErrorRate;
+ ClientFatalError( error );
+ return;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the target size of each coded video segment
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetSegmentTargetSize( TUint aLayer,
+ TUint aSizeBytes,
+ TUint /*aSizeMacroblocks*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ if ( iH264EncInitParams.iDataUnitType == EDuCodedPicture )
+ {
+ if( aSizeBytes== 0 )
+ {
+ if( iIsSliceEnabledInCodedPicture )
+ {
+ iIsSliceEnabledInCodedPicture= EFalse;
+ TInt error = iCodec->SetParam( CONTROL_CMD_SET_FRAME_MODE,
+ NULL );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ }
+ return;
+ }
+ TUint calculatedSegmentSize = 0;
+ if( aSizeBytes <= KH264ENCIMPL_MIN_SLICESIZE )
+ {
+ calculatedSegmentSize = KH264ENCIMPL_MIN_SLICESIZE;
+ }
+ else
+ {
+ if ( iH264EncInitParams.iMaxCodedSegmentSize
+ < iH264EncInitParams.iMaxCodedPictureSize )
+ {
+ if ( aSizeBytes > iH264EncInitParams.iMaxCodedSegmentSize )
+ {
+ calculatedSegmentSize
+ = iH264EncInitParams.iMaxCodedSegmentSize;
+ }
+ else
+ {
+ calculatedSegmentSize = aSizeBytes;
+ }
+ }
+ else
+ {
+ if ( aSizeBytes < iH264EncInitParams.iMaxCodedPictureSize )
+ {
+ calculatedSegmentSize = aSizeBytes;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+ if( calculatedSegmentSize < KH264ENCIMPL_MIN_SLICESIZE )
+ {
+ calculatedSegmentSize = KH264ENCIMPL_MIN_SLICESIZE;
+ }
+
+ TBool yesorno = EFalse;
+ TInt error = iCodec->SetParam( CONTROL_CMD_SET_PACKET_MODE,
+ &yesorno );
+
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ // Set the target size on codec
+ error = iCodec->SetParam( CONTROL_CMD_SET_PACKET_SIZE,
+ &calculatedSegmentSize );
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::calculatedSegmentSize() is %d" ,
+ ( TInt )calculatedSegmentSize ) );
+
+ iH264EncInitParams.iMaxCodedSegmentSize = calculatedSegmentSize;
+ iIsSliceEnabledInCodedPicture = ETrue;
+ return;
+
+ }
+
+ if ( iH264EncInitParams.iDataUnitType != EDuVideoSegment )
+ {
+ return;
+ }
+
+ // aLayer should be zero since layered bit-rate scalability is not used.
+ if ( aLayer != 0 )
+ {
+ return;
+ }
+
+ TUint calculatedSegmentSize = 0;
+ // if value < 0 or > iMaxOutputBufferSize the adjust this value
+ if ( aSizeBytes < KH264ENCIMPL_MIN_SEGMENTSIZE )
+ {
+ calculatedSegmentSize = KH264ENCIMPL_MIN_SEGMENTSIZE;
+ }
+ else
+ {
+ if ( iH264EncInitParams.iMaxOutputBufferSize
+ > KH264ENCIMPL_MAX_SEGMENTSIZE )
+ {
+ if ( aSizeBytes < KH264ENCIMPL_MAX_SEGMENTSIZE )
+ {
+ calculatedSegmentSize = aSizeBytes;
+ }
+ else
+ {
+ calculatedSegmentSize = KH264ENCIMPL_MAX_SEGMENTSIZE;
+ }
+ }
+ else
+ {
+ if ( aSizeBytes < iH264EncInitParams.iMaxOutputBufferSize )
+ {
+ calculatedSegmentSize = aSizeBytes;
+ }
+ else
+ {
+ calculatedSegmentSize
+ = iH264EncInitParams.iMaxOutputBufferSize;
+ }
+ }
+ }
+
+ // Set the target size on codec
+ TInt error = iCodec->SetParam( CONTROL_CMD_SET_PACKET_SIZE,
+ &calculatedSegmentSize );
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ iH264EncInitParams.iMaxCodedSegmentSize = calculatedSegmentSize;
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Sets the bit-rate control options for a layer
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetRateControlOptions( TUint aLayer,
+ const TRateControlOptions& aOptions )
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ // Since layered bit-rate scalability is not used, options are set for the
+ // entire stream
+ if ( aLayer != 0 )
+ {
+ return;
+ }
+
+ if ( ( aOptions.iPictureRate <= 0 ) ||
+ ( aOptions.iControl & EBrControlPicture ) )
+ {
+ return;
+ }
+
+ if ( aOptions.iControl & EBrControlStream )
+ {
+ if ( ( aOptions.iQualityTemporalTradeoff < 0 ) ||
+ ( aOptions.iQualityTemporalTradeoff > 1 ) ||
+ ( aOptions.iLatencyQualityTradeoff < 0 ) ||
+ ( aOptions.iLatencyQualityTradeoff > 1 ) ||
+ ( aOptions.iBitrate == 0 ) )
+ {
+ return;
+ }
+ }
+
+ TRateControlOptions* rateControlOptions = NULL;
+ TRAPD( error, rateControlOptions = new ( ELeave )TRateControlOptions );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ rateControlOptions->iControl = aOptions.iControl;
+ // default bit rate used
+ if( aOptions.iControl & EBrControlNone )
+ {
+ rateControlOptions->iBitrate = iH264EncInitParams.iBitRate;
+ }
+ else
+ {
+ rateControlOptions->iBitrate = ( aOptions.iBitrate
+ <= iH264EncInitParams.iBitRate ) ? ( aOptions.iBitrate )
+ : ( iH264EncInitParams.iBitRate );
+ }
+
+ rateControlOptions->iPictureQuality = aOptions.iPictureQuality;
+ rateControlOptions->iPictureRate = aOptions.iPictureRate;
+ rateControlOptions->iQualityTemporalTradeoff
+ = aOptions.iQualityTemporalTradeoff;
+ rateControlOptions->iLatencyQualityTradeoff
+ = aOptions.iLatencyQualityTradeoff;
+
+ TRAP( error, iEngine->AddCommandL( CBaseEngine::EHighPriority,
+ CONTROL_CMD_SET_RATE_CONTROL_OPTIONS, rateControlOptions ) );
+
+ if( error != KErrNone )
+ {
+ delete rateControlOptions;
+ ClientFatalError ( error );
+ return;
+ }
+
+ if( !iEncStateMac->IsPlaying() )
+ {
+ TInt ret = iCodec->SetParam( CONTROL_CMD_SET_RATE_CONTROL_OPTIONS,
+ rateControlOptions );
+ if ( ret )
+ {
+ ClientFatalError( ret );
+ }
+ }
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ "iBitrate is %d", ( TInt )aOptions.iBitrate ) );
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ "iPictureQuality is %d" , ( TInt )aOptions.iPictureQuality ) );
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ " iPictureRate is %f", ( TReal )aOptions.iPictureRate ) );
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ "iQualityTemporalTradeoff is %f" ,
+ ( TReal )aOptions.iQualityTemporalTradeoff ) );
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ " iLatencyQualityTradeoff is %f " ,
+ ( TReal ) aOptions.iLatencyQualityTradeoff ) );
+
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetRateControlOptions()"
+ "iControl is %x" , ( TInt ) aOptions.iControl ) );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets in-layer scalability options for a layer
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetInLayerScalabilityL( TUint /*aLayer*/,
+ TUint /*aNumSteps*/,
+ TInLayerScalabilityType /*aScalabilityType*/,
+ const TArray<TUint>& /*aBitrateShare*/,
+ const TArray<TUint>& /*aPictureShare*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetInLayerScalabilityL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "SetInLayerScalabilityL () not supported..leaving with "
+ "KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the period for layer promotions points for a scalability layer
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetLayerPromotionPointPeriod( TUint /*aLayer*/,
+ TUint /*aPeriod*/ )
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ ClientFatalError( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Returns coding-standard specific settings output from the encoder
+//----------------------------------------------------------------------------
+//
+HBufC8* CAriH264encHwDeviceImpl::CodingStandardSpecificSettingsOutputLC()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "CodingStandardSpecificSettingsOutputLC () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "CodingStandardSpecificSettingsOutputLC () not supported.."
+ "leaving with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ return NULL;
+ }
+
+//----------------------------------------------------------------------------
+// Returns implementation-specific settings output from the encoder
+//----------------------------------------------------------------------------
+//
+HBufC8* CAriH264encHwDeviceImpl::ImplementationSpecificSettingsOutputLC()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "ImplementationSpecificSettingsOutputLC () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "ImplementationSpecificSettingsOutputLC () not supported.."
+ "leaving with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ return NULL;
+ }
+
+//----------------------------------------------------------------------------
+// Requests the encoder to sends supplemental information in the bitstream
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SendSupplementalInfoL( const TDesC8& /*aData*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SendSupplementalInfoL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "SendSupplementalInfoL () not supported.."
+ "leaving with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Requests the encoder to sends supplemental information in the bitstream
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SendSupplementalInfoL( const TDesC8& /*aData*/,
+ const TTimeIntervalMicroSeconds& /*aTimestamp*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SendSupplementalInfoL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ PRINT_ERR( "SendSupplementalInfoL () not supported.."
+ "leaving with KErrNotSupported" );
+ User::Leave( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Cancels the current supplemental information send request
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::CancelSupplementalInfo()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ ClientFatalError( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Gets the current output buffer status. The information includes
+// the number of free output buffers and the total size of free buffers in
+// bytes.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::GetOutputBufferStatus( TUint& aNumFreeBuffers,
+ TUint& aTotalFreeBytes )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ aNumFreeBuffers = iEngine->NumOutputBuffers()
+ + iOutputFreeBufferQueue.Count();
+
+ aTotalFreeBytes = aNumFreeBuffers * iOutputBufferSize;
+
+ PRINT_EXIT;
+ }
+//----------------------------------------------------------------------------
+// Returns a used output buffer back to the encoder
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ReturnBuffer( TVideoOutputBuffer* aBuffer )
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ // coded picture buffers so add it to Interanal Q or process engine
+ if ( iNumofBuffersPendingFromClientInChangeToPacketMode )
+ {
+ iEngine->AddOutput( aBuffer );
+ --iNumofBuffersPendingFromClientInChangeToPacketMode;
+ return;
+ }
+
+ // buffers returned by the client are
+ if ( iNumOfBuffersAtClientInPacketModeNeedReAllocation )
+ {
+ TRAPD( error, ReallocateSegmentBufferL( aBuffer ) );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ iNumOfBuffersAtClientInPacketModeNeedReAllocation--;
+ }
+
+ TInt error = KErrNone;
+ error = iOutputFreeBufferQueue.Append( aBuffer );
+
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ if ( !iPacketsPending )
+ {
+ return;
+ }
+
+ // still has packets in temporary buffer
+ if ( iTotalLengthFilledSoFarInPacketMode
+ < iTotalOutputBufferLengthInPacketMode )
+ {
+ TVideoOutputBuffer *outBuf = iOutputFreeBufferQueue[0];
+ FillVideoSegment( outBuf, iInternalOutputBufferQueue[0] );
+ iOutputFreeBufferQueue.Remove( 0 );
+
+ #ifdef CALCINSTANTBITRATE
+ CalculateInstantBitRate( *outBuf );
+ #endif
+
+ iMMFDevVideoRecordProxy->MdvrpNewBuffer( outBuf );
+ }
+ }
+ else
+ {
+ aBuffer->iData.Set( ( TUint8* )aBuffer->iData.Ptr(),
+ iOutputBufferSize );
+
+ // add the buffer back to queue or process engine
+ if ( ( !iEncStateMac->IsInputEndPending() )
+ && ( !iEncStateMac->IsStopped() ) )
+ {
+ iEngine->AddOutput( ( TAny* )aBuffer );
+ }
+ else
+ {
+ TInt error = iOutputFreeBufferQueue.Append( aBuffer );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Indicates a picture loss to the encoder, without specifying the lost
+// picture
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::PictureLoss()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ iPictureLoss = ETrue;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Indicates to the encoder the pictures that have been lost
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::PictureLoss(
+ const TArray<TPictureId>& /*aPictures*/ )
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ iPictureLoss = ETrue;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Indicates a slice loss to the encoder.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SliceLoss( TUint aFirstMacroblock,
+ TUint aNumMacroblocks,
+ const TPictureId& /*aPicture*/ )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ if ( ( aFirstMacroblock == 0 ) || ( aNumMacroblocks == 0 ) )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SliceLoss() "
+ "aNumMacroblocks or aFirstMacroblock = 0 return" ) );
+ return;
+ }
+
+ TH264EncSliceLoss* sliceLossParams = NULL;
+ TRAPD( error, sliceLossParams = new( ELeave ) TH264EncSliceLoss );
+ if( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ sliceLossParams->iFirstMacroblock = aFirstMacroblock;
+ sliceLossParams->iNumMacroblocks = aNumMacroblocks;
+
+ TRAP( error, iEngine->AddCommandL( CBaseEngine::ENormalPriority,
+ CONTROL_CMD_SET_SLICELOSS, sliceLossParams ) );
+
+ if( error != KErrNone )
+ {
+ delete sliceLossParams;
+ ClientFatalError ( error );
+ return;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sends a reference picture selection request to the encoder
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ReferencePictureSelection(
+ const TDesC8& /*aSelectionData*/)
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ ClientFatalError( KErrNotSupported );
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Initializes the device, and reserves hardware resources
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Initialize()
+ {
+ PRINT_ENTRY;
+
+ //Device should be in unintialized state
+ if ( !iEncStateMac->IsTransitionValid(
+ CStateMachine::EInitializingCommand ) )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete(this
+ , KErrPermissionDenied );
+ return;
+ }
+
+ // check for input and output formats set by the client
+ if ( ! ( iH264EncInitParams.iBeforeInitialize & EEncInputFormat ) )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ("CAriH264encHwDeviceImpl::Initialize() "
+ "- SetInputFormat not called" ) );
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this,
+ KErrNotSupported );
+ return;
+ }
+
+ // check for buffer sizes
+ if( iH264EncInitParams.iBeforeInitialize & EEncBufferOptions )
+ {
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ // Buffer size related checks
+ if ( ( iH264EncInitParams.iMaxOutputBufferSize >
+ ( KH264ENCIMPL_FACTOR_FOR_OUTPUTBUFFERSIZE_IN_PACKETMODE *
+ KH264ENCIMPL_MAX_SEGMENTSIZE ) ) ||
+ ( iH264EncInitParams.iMaxCodedSegmentSize >
+ KH264ENCIMPL_MAX_SEGMENTSIZE ) ||
+ ( iH264EncInitParams.iMaxCodedSegmentSize >
+ iH264EncInitParams.iMaxOutputBufferSize ) ||
+ ( iH264EncInitParams.iMaxCodedSegmentSize == 0 ) )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ( "CAriH264encHwDeviceImpl"
+ "::Initialize() - Wrong size for iMaxCodedSegmentSize" ) );
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this,
+ KErrNotSupported );
+ return;
+ }
+ }
+
+ else if ( iH264EncInitParams.iDataUnitType == EDuCodedPicture )
+ {
+ if ( ( iH264EncInitParams.iMaxCodedPictureSize >
+ iH264EncInitParams.iMaxOutputBufferSize )
+ || ( iH264EncInitParams.iMaxCodedPictureSize == 0 ) )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ( "CAriH264encHwDeviceImpl"
+ "::Initialize() - Wrong size for iMaxCodedPictureSize" ) );
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this,
+ KErrNotSupported );
+ return;
+ }
+ }
+ }
+ else
+ {
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ iH264EncInitParams.iMinNumOutputBuffers
+ = KH264ENCIMPL_MAXNUM_SEGMENTBUFFERS;
+ iH264EncInitParams.iMaxCodedSegmentSize
+ = KH264ENCIMPL_DEFAULT_SEGMENTSIZE;
+ iH264EncInitParams.iMaxOutputBufferSize
+ = KH264ENCIMPL_MAX_SEGMENTSIZE;
+ }
+ else
+ {
+ iH264EncInitParams.iMinNumOutputBuffers
+ = KH264ENCIMPL_MAXNUM_OUTPUTBUFFERS;
+ }
+ }
+
+ // based on level set the max bit rate
+ switch ( iH264EncInitParams.iLevel )
+ {
+ //Level 1b
+ case KH264ENCIMPL_LEVEL_1b:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_1b;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ break;
+
+ case KH264ENCIMPL_LEVEL_1:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_1;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ break;
+
+ case KH264ENCIMPL_LEVEL_11:
+ // Both Level 1b and 1.1 have this value
+ // need to decide if 1.1 or 1.b
+ // two options - client passes buffer options and client doesnt
+ // pass buffer options
+ {
+ TBool isLevel1b = EFalse;
+ if ( iH264EncInitParams.iBeforeInitialize & EEncBufferOptions )
+ {
+ isLevel1b = ( ( KH264ENCIMPL_LEVEL1b_MAXCPBSIZE <=
+ iH264EncInitParams.iMaxCodedPictureSize ) &&
+ ( iH264EncInitParams.iMaxCodedPictureSize <
+ KH264ENCIMPL_LEVEL11_MAXCPBSIZE ) )
+ ? ( ETrue )
+ : ( EFalse );
+ }
+ //now we have input size information to decide 1b vs 1.1
+ else
+ {
+ isLevel1b = ( ( iH264EncInitParams.iPictureSize.iWidth >
+ KH264ENCIMPL_QCIF_WIDTH )
+ && ( iH264EncInitParams.iPictureSize.iHeight >
+ KH264ENCIMPL_QCIF_HEIGHT ) )
+ ? ( EFalse )
+ : ( ETrue );
+ }
+
+ if ( isLevel1b )
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_1b;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_1b;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ }
+ else
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_11;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_11;
+ iH264EncInitParams.iTargetPictureRate
+ = ( ( iH264EncInitParams.iPictureSize.iWidth
+ <= KH264ENCIMPL_QCIF_WIDTH ) &&
+ ( iH264EncInitParams.iPictureSize.iHeight
+ <= KH264ENCIMPL_QCIF_HEIGHT ) ) ? ( KPictureRate15 )
+ : ( KPictureRate75 );
+ }
+ }
+ break;
+
+ case KH264ENCIMPL_LEVEL_12:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_12;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ break;
+
+ case KH264ENCIMPL_LEVEL_13:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_13;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate30;
+ break;
+
+ case KH264ENCIMPL_LEVEL_2:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_2;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate30;
+ break;
+
+ case KH264ENCIMPL_LEVEL_21:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_21;
+ if ( iH264EncInitParams.iPictureSize.iHeight >
+ KH264ENCIMPL_HALFSDTV_HEIGHT_NTSC )
+ {
+ // HALFSDTV-PAL
+ iH264EncInitParams.iTargetPictureRate = KPictureRate25;
+ }
+ else
+ {
+ // HALFSDTV-NTSC
+ iH264EncInitParams.iTargetPictureRate = KPictureRate30;
+ }
+ break;
+
+ case KH264ENCIMPL_LEVEL_22:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_22;
+ if ( iH264EncInitParams.iPictureSize.iHeight >
+ KH264ENCIMPL_SDTV_HEIGHT_NTSC )
+ {
+ // SDTV-PAL
+ iH264EncInitParams.iTargetPictureRate
+ = KH264ENCIMPL_PICTURERATE_12_5;
+ }
+ else
+ {
+ // SDTV-NTSC
+ iH264EncInitParams.iTargetPictureRate
+ = KPictureRate15;
+ }
+ break;
+
+ case KH264ENCIMPL_LEVEL_3:
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_3;
+ if ( iH264EncInitParams.iPictureSize.iHeight
+ > KH264ENCIMPL_SDTV_HEIGHT_NTSC )
+ {
+ iH264EncInitParams.iTargetPictureRate = KPictureRate25;
+ }
+ else
+ {
+ // SDTV-NTSC
+ iH264EncInitParams.iTargetPictureRate = KPictureRate30;
+ }
+ break;
+
+ // level unknown based on size decide bitrate and level
+ case 0:
+ SetLevelAndBitRate();
+ break;
+
+ default:
+ break;
+ };
+
+ // create codec
+ TRAPD( error, iCodec = CAriH264encWrapper::NewL( iH264EncInitParams ) );
+ if( error != KErrNone )
+ {
+ // init complete with error message
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ // set the sync options to the codec
+ if( iClockSource )
+ {
+ TInt error = iCodec->SetSyncOptions( iClockSource );
+
+ if( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+ }
+ //Check whether picture is of QCIF format if VT fast call setup is set
+
+ if ( iH264EncInitParams.iVTFastCallSetUp )
+ {
+ if ( iH264EncInitParams.iPictureSize.iWidth
+ != KH264ENCIMPL_QCIF_WIDTH ||
+ iH264EncInitParams.iPictureSize.iHeight
+ != KH264ENCIMPL_QCIF_HEIGHT )
+ {
+ PRINT_MSG( LEVEL_LOW, ("Input resolution should be 176x144 for"
+ " VT Fast call setup" ) );
+ ClientFatalError( KErrNotSupported );
+ }
+ }
+
+ if ( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ //create engine
+ TRAP( error, iEngine = CBaseEngine::NewL( this,
+ ( MBaseCodec* ) iCodec, EFalse ) );
+
+ if( error != KErrNone )
+ {
+ //init complete with error message
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+ //get the max buffer length from the codec
+ TInt maxOutputBufferSize = 0;
+ error = iCodec->GetParam( CONTROL_CMD_GET_MAX_FRAME_SIZE,
+ &maxOutputBufferSize );
+
+ if( error != KErrNone )
+ {
+ //init complete with error message
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ // if EduCodedPicture mode then check for buffer size passed
+ if( iH264EncInitParams.iDataUnitType == EDuCodedPicture )
+ {
+ if ( iH264EncInitParams.iBeforeInitialize & EEncBufferOptions )
+ {
+ if( maxOutputBufferSize
+ > iH264EncInitParams.iMaxCodedPictureSize )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::Initialize()"
+ "maxOutputBufferSize = %d", ( TInt ) maxOutputBufferSize ) );
+ //init complete with error message
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete(this,
+ KErrNotSupported );
+ return;
+ }
+ }
+ else
+ {
+ iH264EncInitParams.iMaxOutputBufferSize = maxOutputBufferSize;
+ iH264EncInitParams.iMaxCodedPictureSize = maxOutputBufferSize;
+ }
+ }
+
+ // if packet mode is on then allocate memory for NAL information
+ TUint maxNumOfPackets = 0;
+ if( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ error = iCodec->GetParam( CONTROL_CMD_GET_MAX_NUM_PACKETS,
+ &iMaxNumOfPackets );
+ if( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+ }
+
+ if ( iH264EncInitParams.iDataUnitType != EDuVideoSegment )
+ {
+ TInt maxSlices = 0;
+ if( maxOutputBufferSize )
+ {
+ maxSlices = maxOutputBufferSize / KH264ENCIMPL_MIN_SLICESIZE;
+ if( maxOutputBufferSize % KH264ENCIMPL_MIN_SLICESIZE )
+ {
+ maxSlices++;
+ }
+ }
+
+#ifndef EMZ_AVC_ENC_CODEC_SEIINFO_ENABLE
+ PRINT_MSG( LEVEL_LOW, ( "CreateCodedOutputBuffersL SEI disble " ) );
+
+ // included KNumOfConfigParams*KDoubleWordLength bytes which are
+ // required for filling offset length information
+
+ TRAP( error, CreateCodedOutputBuffersL( ( maxOutputBufferSize +
+ KWordLength + ( ( KNumOfConfigParams + maxSlices )
+ * KDoubleWordLength ) ) ) );
+#else
+ PRINT_MSG( LEVEL_LOW, ("CreateCodedOutputBuffersL SEI enable " ) );
+ TRAP( error, CreateCodedOutputBuffersL( ( maxOutputBufferSize +
+ KWordLength + ( ( KNumOfNAL_SEI + maxSlices ) *
+ KDoubleWordLength ) ) ) );
+#endif
+ }
+ else
+ {
+ // Allocate sufficient segment mode buffers Comment it for some time.
+ iH264EncInitParams.iMinNumOutputBuffers = ( maxOutputBufferSize /
+ iH264EncInitParams.iMaxCodedSegmentSize ) *
+ KH264ENCIMPL_MAXNUM_OUTPUTBUFFERS;
+
+ // holds output buffer 2. holds packet lenght and offset information
+ TRAP( error, CreateInternalOutputBuffersL( maxOutputBufferSize ) );
+ if( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ TRAP( error, CreatePacketOffsetLengthInfoBuffersL( iMaxNumOfPackets *
+ KDoubleWordLength ) );
+ if( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ //segement size will be the max segment size
+ TUint segmentSize = iH264EncInitParams.iMaxOutputBufferSize;
+ if ( ( iH264EncInitParams.iDataEncapsulation == EDuGenericPayload ) &&
+ ( iH264EncInitParams.iMaxOutputBufferSize <
+ ( KH264ENCIMPL_MAX_SEGMENTSIZE + KDoubleWordLength
+ + KWordLength ) ) )
+ {
+ segmentSize += KDoubleWordLength + KWordLength;
+ }
+
+ TRAP( error, CreateCodedOutputBuffersL( segmentSize ) );
+ if( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+ }
+
+ if ( error != KErrNone )
+ {
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, error );
+ return;
+ }
+
+ //reset the picture counters
+ iPictureCounters.iInputPictures = 0;
+ iPictureCounters.iPicturesSkippedRateControl = 0;
+ iPictureCounters.iPicturesProcessed = 0;
+
+ // reset the options set by client
+ iH264EncInitParams.iBeforeInitialize = 0;
+ iCurSetH264EncParams = iH264EncInitParams;
+ iEncStateMac->Transit( CStateMachine::EInitializingCommand );
+ iEncStateMac->Transit( CStateMachine::EInitializeCommand );
+ iMMFDevVideoRecordProxy->MdvrpInitializeComplete( this, KErrNone );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Commit all changes since the last CommitL(), Revert() or Initialize()
+// to the Hw device
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::CommitL()
+ {
+ PRINT_ENTRY;
+
+ // This method can only be called after Initialize
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "CommitL () called before "
+ "Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ // Methods that will be affected by CommitL in our case:
+ // SetOutputRectL
+ // SetCodingStandardSpecificOptionsL
+ // SetErrorsExpected
+ // SetMinRandomAccessRate
+
+ TH264EncInitParams *currentParams = new( ELeave ) TH264EncInitParams;
+ CleanupStack::PushL( currentParams );
+ *currentParams = iCurSetH264EncParams;
+
+ // Add command apply commit settings to the codec
+ iEngine->AddCommandL ( CBaseEngine::ENormalPriority,
+ CONTROL_CMD_SET_COMMIT_OPTIONS, currentParams );
+
+ iCurSetH264EncParams.iAfterInitialize = 0;
+ CleanupStack::Pop();
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Revert all changes since the last CommitL(), Revert() or Initialize()
+// back to their previous settings
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Revert()
+ {
+ PRINT_ENTRY;
+
+ // This method can only be called after Initialize
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ // Methods that will be affected by Revert in our case:
+ // SetOutputRectL
+ // SetCodingStandardSpecificOptionsL
+ // SetErrorsExpected
+ // SetMinRandomAccessRate
+
+ iCurSetH264EncParams = iH264EncInitParams;
+ iCurSetH264EncParams.iAfterInitialize = 0;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// This method is called only in case of client memory buffers
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::WritePictureL( TVideoPicture* aPicture )
+ {
+ PRINT_ENTRY;
+
+ // This method should only be called only in following states
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "WritePictureL () called before Initialize ()" );
+ User::Leave( KErrNotReady );
+ }
+
+ if( iEncStateMac->IsInputEndPending() )
+ {
+ PRINT_ERR( "Input end is pending.. leaving with KErrEof" );
+ User::Leave( KErrEof );
+ }
+
+ if( !aPicture ||
+ ( aPicture->iData.iRawData->Length() == 0 ) ||
+ ( aPicture->iData.iRawData->Length() !=
+ ( ( iH264EncInitParams.iPictureSize.iWidth *
+ iH264EncInitParams.iPictureSize.iHeight * 3 ) / 2 ) ) ||
+ ( aPicture->iData.iDataFormat != EYuvRawData ) )
+ {
+ PRINT_ERR( "Incorrect parameter passed" );
+ User::Leave( KErrArgument );
+ return;
+ }
+
+ // Added a check to return the input picture if application tries to add
+ // pictures after calling InputEnd() or Stop() and before calling
+ // Start() again.
+
+ if ( iEncStateMac->IsStopped() )
+ {
+ SkipInputPicture( aPicture );
+ return;
+ }
+
+ // counter to represent the num of input pictures received
+ iPictureCounters.iInputPictures++;
+ if( IsForcedIFrameRequired( aPicture ) )
+ {
+ iEngine->AddCommandL( CBaseEngine::ENormalPriority,
+ CONTROL_CMD_SET_FORCED_I_FRAME, NULL );
+ iPictureLoss = EFalse;
+ }
+
+ //Check if clock source is enabled skip logic
+ if ( iClockSource )
+ {
+ if ( ( !CanEncode( aPicture ) ) || iFrozen )
+ {
+ SkipInputPicture( aPicture );
+ return;
+ }
+ }
+
+ TInt error = iEngine->AddInput( aPicture );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "CAriH264encHwDeviceImpl::WritePictureL()"
+ " AddInput() failed" );
+ User::Leave( error );
+ return;
+ }
+
+ if( this->iH264EncInitParams.iProcessRealtime )
+ {
+ // Check the iDataUnitType
+ if( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ TInt perPictureSegmentBuffers
+ = iH264EncInitParams.iMinNumOutputBuffers
+ / KH264ENCIMPL_MAXNUM_OUTPUTBUFFERS;
+ TInt queueCount = iOutputFreeBufferQueue.Count();
+ // Check for availability of segment buffers
+ if ( queueCount < perPictureSegmentBuffers )
+ {
+ // Sufficient number of segment buffers are not present
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl"
+ "::WritePictureL() Input returned EDuVideoSegment " ) );
+ // Return the earlier input picture added to the queue
+ iEngine->ReturnInput();
+ return;
+ }
+ }
+ else
+ {
+ // Check for availability of buffers.
+ if ( iEngine->NumOutputBuffers() == 0 )
+ {
+ // Return the earlier input picture added to the queue
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::WritePictureL() Input returned EDuCodedPicture " ) );
+ iEngine->ReturnInput();
+ return;
+ }
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Notifies the hardware device that the end of input data has been reached
+// and no more input pictures will be written
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::InputEnd()
+ {
+ PRINT_ENTRY;
+
+ if ( !iEncStateMac->IsTransitionValid( CStateMachine::EInputEndCommand ) )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ if ( iEngine->NumInputBuffers() == 0 )
+ {
+ PRINT_MSG( LEVEL_HIGH, ("CAriH264encHwDeviceImpl::InputEnds()" ) );
+ Stop();
+ iMMFDevVideoRecordProxy->MdvrpStreamEnd();
+ return;
+ }
+ else
+ {
+ iInputEndCalled = ETrue;
+ }
+
+ iEncStateMac->Transit( CStateMachine::EInputEndCommand );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Starts recording video
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Start()
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsPlaying() && !iEncStateMac->IsPaused() )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::Start()-already in"
+ "started state, So ignore" ) );
+ return;
+ }
+
+ if( !iEncStateMac->IsTransitionValid( CStateMachine::EStartCommand ) )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ // Enable flag which indicates that all picture params and sequence
+ // params are put into 1st buffer
+ iIsConfigDataFilledInFirstOutputBuffer = ETrue;
+ for( TInt i = 0; i <= iInternalOutputBufferQueue.Count(); i++ )
+ {
+ TVideoOutputBuffer *outputBuffer = iInternalOutputBufferQueue[0];
+ iEngine->AddOutput( ( TAny* )outputBuffer );
+ iInternalOutputBufferQueue.Remove( 0 );
+ }
+ }
+ else
+ {
+ // add all output buffers to engine
+ for( TInt i = 0; i <= iOutputFreeBufferQueue.Count(); i++ )
+ {
+ TVideoOutputBuffer *outputBuffer = iOutputFreeBufferQueue[0];
+ iEngine->AddOutput( ( TAny* )outputBuffer );
+ iOutputFreeBufferQueue.Remove( 0 );
+ }
+ }
+
+ if ( iClockSource )
+ {
+ TTime lSystemTime;
+ lSystemTime.UniversalTime();
+ UpdateTime();
+ iPeriodicTimer->Start( iPollingInterval, iPollingInterval,
+ TCallBack( CAriH264encHwDeviceImpl::TimerCallBack, ( TAny* )this ) );
+ }
+
+ iEngine->Start();
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::Start() Change to "
+ " start state** ") ) ;
+ iEncStateMac->Transit( CStateMachine::EStartCommand );
+
+ PRINT_EXIT;
+
+ }
+
+//----------------------------------------------------------------------------
+// Callback function to CPeriodicTimer object
+//----------------------------------------------------------------------------
+//
+TInt CAriH264encHwDeviceImpl::TimerCallBack( TAny* aPtr )
+ {
+ PRINT_ENTRY;
+ if ( !aPtr )
+ {
+ ( ( CAriH264encHwDeviceImpl* )aPtr )->ClientFatalError(
+ KErrArgument );
+ return KErrNone;
+ }
+ PRINT_EXIT;
+ return ( ( CAriH264encHwDeviceImpl* )aPtr )->UpdateTime();
+ }
+
+//----------------------------------------------------------------------------
+// Stops recording video.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Stop()
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsStopped() )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::Stop() -> already "
+ "in stop state, so ignore" ) );
+ return;
+ }
+
+ if( !iEncStateMac->IsTransitionValid( CStateMachine::EStopCommand ) )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ("CAriH264encHwDeviceImpl::Stop() -> "
+ "fatalerror because Stop called in invalid state" ) );
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ iInputEndCalled = EFalse;
+ iIsSliceEnabledInCodedPicture = EFalse;
+
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ // new clip started so config data has to be filled in first output
+ // buffer
+ iIsConfigDataFilledInFirstOutputBuffer = ETrue;
+ iTotalOutputBufferLengthInPacketMode = 0;
+ iTotalLengthFilledSoFarInPacketMode = 0;
+ iPacketsPending = EFalse;
+ }
+
+ iEngine->Stop();
+ iEngine->Reset();
+
+ iFrozen = EFalse;
+ if( iPeriodicTimer )
+ {
+ iPeriodicTimer->Cancel();
+ }
+ iEncStateMac->Transit( CStateMachine::EStopCommand );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Pauses video recording
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Pause()
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsPaused() )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::Pause()-> already"
+ "in Paused state, so ignore" ) );
+ return;
+ }
+
+ if( !iEncStateMac->IsTransitionValid( CStateMachine::EPauseCommand ) )
+ {
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::Pause() Pause "
+ "called in invalid state" ) );
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ // No arguments to be passed in Pause
+ if( iClockSource )
+ {
+ iPeriodicTimer->Cancel();
+ //Note down the clock when paued
+ iClockTimeWhenPaused = iClockSource->Time().Int64();
+ }
+
+ // Stop the engine
+ iEngine->Stop();
+
+ //Change the state of the encoder
+ iEncStateMac->Transit( CStateMachine::EPauseCommand );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Resumes video recording
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Resume()
+ {
+ PRINT_ENTRY;
+
+ // doing it before transitionvalid check because initialize->resume is
+ // not added
+ if( iEncStateMac->IsInInitializedState() )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::Resume()->Got resume"
+ " in initialized state. So go to start()" ) );
+ Start();
+ return;
+ }
+
+ if( iEncStateMac->IsPlaying() && !iEncStateMac->IsPaused() )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::Resume()->already in"
+ " playing-not-paused state, so ignore" ) );
+ return;
+ }
+
+ if( !iEncStateMac->IsTransitionValid( CStateMachine::EResumeCommand ) )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ("Resume called in invalid state" ) );
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ // No arguments to be passed in Resume
+ if ( iClockSource )
+ {
+ //Clock may or may not be paused, when HWDevice is paused, so
+ //add the paused duration to clock
+ iPauseOffset = iClockSource->Time().Int64();
+ iPauseOffset -= iClockTimeWhenPaused;
+
+ //calculate the total time and deviation
+ iTotalTime += iPauseOffset;
+ TTime lSystemTime;
+ lSystemTime.UniversalTime();
+
+ // Send Update time before sending Resume command, so that clock
+ // source is set before
+
+ UpdateTime ();
+ iPeriodicTimer->Start( iPollingInterval, iPollingInterval,
+ TCallBack( CAriH264encHwDeviceImpl::TimerCallBack, ( TAny* )this ) );
+ }
+
+ // Start the engine
+ iEngine->Start();
+
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+
+ // send the remaining pending packets to client
+ while ( iOutputFreeBufferQueue.Count() && iPacketsPending )
+ {
+ TVideoOutputBuffer *outBuf = iOutputFreeBufferQueue[0];
+ FillVideoSegment( outBuf, iInternalOutputBufferQueue[0] );
+ iOutputFreeBufferQueue.Remove( 0 );
+
+ #ifdef CALCINSTANTBITRATE
+ CalculateInstantBitRate( *outBuf );
+ #endif
+
+ iMMFDevVideoRecordProxy->MdvrpNewBuffer( outBuf );
+ }
+ }
+ //Change the state of the encoder
+ iEncStateMac->Transit( CStateMachine::EResumeCommand );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Freezes the input picture
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::Freeze()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ("CAriH264encHwDeviceImpl::Freeze() Freeze"
+ " called in invalid state" ) );
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ iFrozen = ETrue;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Releases a frozen input picture
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ReleaseFreeze()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::ReleaseFreeze() "
+ "called in invalid state" ) );
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ iFrozen = EFalse;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Returns the current recording position
+//----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CAriH264encHwDeviceImpl::RecordingPosition()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ PRINT_MSG( LEVEL_HIGH, ("CAriH264encHwDeviceImpl::RecordingPosition()"
+ " called in invalid state" ) );
+ ClientFatalError( KErrNotReady );
+ return TTimeIntervalMicroSeconds( 0 );
+ }
+
+ PRINT_EXIT;
+ return TTimeIntervalMicroSeconds( iLastEncodedPictureTimestamp );
+ }
+
+//----------------------------------------------------------------------------
+// Reads various counters related to processed video pictures
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::GetPictureCounters(
+ CMMFDevVideoRecord::TPictureCounters& aCounters )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+ TUint numofpacktsskipped;
+ TUint err = iCodec->GetParam( CONTROL_CMD_GET_PICTURES_SKIPPED,
+ &numofpacktsskipped );
+ if ( err )
+ {
+ ClientFatalError( err );
+ return;
+ }
+
+ iPictureCounters.iPicturesSkippedRateControl
+ = iPictureCounters.iPicturesSkippedRateControl + numofpacktsskipped;
+
+ iPictureCounters.iPicturesProcessed
+ = iPictureCounters.iInputPictures
+ - iPictureCounters.iPicturesSkippedRateControl;
+
+ aCounters = iPictureCounters;
+
+ //reset the counters
+ iPictureCounters.iInputPictures = 0;
+ iPictureCounters.iPicturesSkippedRateControl = 0;
+ iPictureCounters.iPicturesProcessed = 0;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Reads the frame stabilisation output picture position.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::GetFrameStabilisationOutput( TRect&/* aRect*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_EXIT;
+ ClientFatalError( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Retrieves the number of complexity control levels available for this
+// hardware device
+//----------------------------------------------------------------------------
+//
+TUint CAriH264encHwDeviceImpl::NumComplexityLevels()
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return 0;
+ }
+
+ PRINT_EXIT;
+ return( KH264ENCIMPL_NUM_COMPLEXITYLEVELS );
+ }
+
+//----------------------------------------------------------------------------
+// Sets the complexity level to use for video processing in a hardware device
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetComplexityLevel( TUint aLevel )
+ {
+ PRINT_ENTRY;
+
+ if( !iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrNotReady );
+ return;
+ }
+
+ if( aLevel >= KH264ENCIMPL_NUM_COMPLEXITYLEVELS )
+ {
+ PRINT_MSG( LEVEL_CRITICAL, ("CAriH264encHwDeviceImpl"
+ "::SetComplexityLevel() Unsupported level Passed" ) );
+ ClientFatalError( KErrArgument );
+ }
+
+ iH264EncInitParams.iComplexityLevel = aLevel;
+ TH264EncInitParams *currentParams = NULL;
+ TRAPD( error, currentParams = new( ELeave ) TH264EncInitParams );
+ *currentParams = iH264EncInitParams;
+
+ // Add command apply commit settings to the codec
+ TRAP( error, iEngine->AddCommandL( CBaseEngine::ENormalPriority,
+ CONTROL_CMD_SET_COMPLEXITY_LEVEL, currentParams ) );
+
+ if( error != KErrNone )
+ {
+ delete currentParams;
+ ClientFatalError( error );
+ return;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Retrieves information about the pre-processing capabilities of this
+// hardware device.
+//----------------------------------------------------------------------------
+//
+CPreProcessorInfo* CAriH264encHwDeviceImpl::PreProcessorInfoLC()
+ {
+ PRINT_ENTRY;
+
+ TInt cleanupstackpushcount = 0;
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetErrorProtectionLevelsL () called after Initialize()"
+ "..leaving" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ _LIT( KManufacturer, "" );
+ _LIT( KIdentifier, "" );
+
+ TPtrC8 implementationSpecificInfo( NULL,0 );
+ RArray<TUncompressedVideoFormat> inputFormats;
+ CleanupClosePushL( inputFormats );
+ cleanupstackpushcount++;
+ inputFormats.Reset();
+
+ RArray<TUncompressedVideoFormat> outputFormats;
+ CleanupClosePushL( outputFormats );
+ cleanupstackpushcount++;
+ outputFormats.Reset();
+
+ RArray<TUint32> supportedCombinations;
+ CleanupClosePushL( supportedCombinations );
+ cleanupstackpushcount++;
+ supportedCombinations.Reset();
+
+ RArray<TScaleFactor> supportedScaleFactors;
+ CleanupClosePushL( supportedScaleFactors );
+ cleanupstackpushcount++;
+ supportedScaleFactors.Reset();
+
+ TYuvToYuvCapabilities yuvToYuvCapabilities;
+ TUid uid;
+
+ CPreProcessorInfo *preProcessorInfo = CPreProcessorInfo::NewL( uid.Null(),
+ KManufacturer,
+ KIdentifier,
+ TVersion( 0,0,0 ),
+ EFalse,
+ EFalse,
+ inputFormats.Array(),
+ outputFormats.Array(),
+ supportedCombinations.Array(),
+ EFalse,
+ EFalse,
+ supportedScaleFactors.Array(),
+ yuvToYuvCapabilities,
+ 0,
+ 0,
+ implementationSpecificInfo );
+
+ CleanupStack::PushL( preProcessorInfo );
+ CleanupStack::Pop( cleanupstackpushcount );
+
+ PRINT_EXIT;
+ return preProcessorInfo ;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the hardware device input format
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetInputFormatL(
+ const TUncompressedVideoFormat& aFormat, const TSize& aPictureSize )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetInputFormatL () called after Initialize()..leaving" );
+ User::Leave( KErrPermissionDenied );
+ }
+
+ if( !CheckInputFormat( aFormat ) )
+ {
+ PRINT_ERR("CAriH264encHwDeviceImpl"
+ "::SetInputFormatL() Leaving because of not support input format" );
+ User::Leave( KErrNotSupported );
+ }
+
+ // Check if passed size is supported by encoder
+ // Check if encoder supports the passed input format
+ // supports all sizes which are multiple of 16 pixels
+
+ if ( ( !aPictureSize.iWidth ) || ( !aPictureSize.iHeight ) ||
+ ( aPictureSize.iWidth % 16 ) || ( aPictureSize.iHeight % 16 ) ||
+ ( aPictureSize.iWidth > KH264ENCIMPL_SDTV_WIDTH ) ||
+ ( aPictureSize.iHeight > KH264ENCIMPL_SDTV_HEIGHT_PAL ) )
+ {
+ PRINT_ERR( "Incorrect parameter passed.. leaving" );
+ User::Leave( KErrNotSupported );
+ }
+
+ TInt32 aspectratio = ::MapAspectRatio(
+ aFormat.iYuvFormat.iAspectRatioNum,
+ aFormat.iYuvFormat.iAspectRatioDenom );
+
+ if ( aspectratio == -1 )
+ {
+ PRINT_ERR( "Aspect ratio is -1.. leaving" );
+ User::Leave( KErrNotSupported );
+ }
+
+ iH264EncInitParams.iAspectRatio = aspectratio;
+ iH264EncInitParams.iInputFormat = aFormat;
+ iH264EncInitParams.iPictureSize = aPictureSize;
+ iH264EncInitParams.iBeforeInitialize |= EEncInputFormat;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the data source to be a camera, and sets the device to use direct
+// capture for input.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetSourceCameraL( TInt /*aCameraHandle*/,
+ TReal /*aPictureRate*/ )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetSourceCameraL() called after Initialize()..leaving" );
+ User::Leave( KErrPermissionDenied );
+ return;
+ }
+
+ User::Leave( KErrNotSupported );
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets the data source to be memory buffers.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetSourceMemoryL( TReal aMaxPictureRate,
+ TBool aConstantPictureRate,
+ TBool aProcessRealtime )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_ERR( "SetSourceMemoryL() called after Initialize()..leaving" );
+ User::Leave( KErrPermissionDenied );
+ return;
+ }
+
+ if( ( aMaxPictureRate <= 0 ) ||
+ ( aMaxPictureRate > KH264ENCIMPL_MAX_PICTURERATE ) )
+ {
+ PRINT_ERR( "Incorrect value of max picture rate..leaving" );
+ User::Leave( KErrNotSupported );
+ return;
+ }
+
+ // Check for the picture rates supported
+ PRINT_MSG( LEVEL_LOW, ( "CAriH264encHwDeviceImpl::SetSourceMemoryL() "
+ "Memory Picture rate is set as %f", aMaxPictureRate ) );
+
+ iH264EncInitParams.iMaxPictureRate = aMaxPictureRate;
+ iH264EncInitParams.iConstantPictureRate = aConstantPictureRate;
+ iH264EncInitParams.iProcessRealtime = aProcessRealtime;
+ iH264EncInitParams.iBeforeInitialize |= EEncSourceMemory;
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Sets the clock source to use for video timing. If no clock
+// source is set. video encoding will not be synchronized, but
+// will proceed as fast as possible, depending on input data and
+// output buffer availability.
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetClockSource( MMMFClockSource* aClock )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return;
+ }
+
+ if( !aClock )
+ {
+ ClientFatalError( KErrArgument );
+ return;
+ }
+
+ PRINT_MSG( LEVEL_LOW, ( " CAriH264encHwDeviceImpl::SetClockSource() "
+ "encoder clockSource is %x", ( TInt ) aClock ) );
+
+ iClockSource = aClock;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for RGB to YUV color space conversion
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetRgbToYuvOptionsL( TRgbRange /*aRange*/,
+ const TYuvFormat& /*aOutputFormat*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetRgbToYuvOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for YUV to YUV data format conversion
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetYuvToYuvOptionsL(
+ const TYuvFormat& /*aInputFormat*/,
+ const TYuvFormat& /*aOutputFormat*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetYuvToYuvOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets the pre-processing types to be used in a hardware device
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetPreProcessTypesL(
+ TUint32 /*aPreProcessTypes*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetPreProcessTypesL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for rotation
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetRotateOptionsL(
+ TRotationType /*aRotationType*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetRotateOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for scaling
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetScaleOptionsL( const TSize& /*aTargetSize*/,
+ TBool /*aAntiAliasFiltering*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetScaleOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for input cropping
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetInputCropOptionsL( const TRect& /*aRect*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetInputCropOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for output cropping
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetOutputCropOptionsL( const TRect& /*aRect*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetOutputCropOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets pre-processing options for output padding
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetOutputPadOptionsL(
+ const TSize& /*aOutputSize*/, const TPoint& /*aPicturePos*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetOutputPadOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets color enhancement pre-processing options
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetColorEnhancementOptionsL(
+ const TColorEnhancementOptions& /*aOptions*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetColorEnhancementOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets frame stabilisation options
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetFrameStabilisationOptionsL(
+ const TSize& /*aOutputSize*/, TBool /*aFrameStabilisation*/ )
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetFrameStabilisationOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Sets custom implementation-specific pre-processing options.
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SetCustomPreProcessOptionsL(
+ const TDesC8& /*aOptions*/)
+ {
+ PRINT_ENTRY;
+ PRINT_ERR( "SetCustomPreProcessOptionsL not supported...leaving \n" );
+ PRINT_EXIT;
+ User::Leave( KErrNotSupported );
+ }
+
+//----------------------------------------------------------------------------
+// Proxy which recieves callbacks from Hw Device
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetProxy( MMMFDevVideoRecordProxy& aProxy )
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ ClientFatalError( KErrPermissionDenied );
+ return ;
+ }
+ iMMFDevVideoRecordProxy = &aProxy;
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Callback to indicate the input buffer is consumed
+//----------------------------------------------------------------------------
+//
+
+TInt CAriH264encHwDeviceImpl::InputBufferConsumed ( TAny* aInp, TInt aError )
+ {
+ PRINT_ENTRY;
+
+ if( !aInp )
+ {
+ return KErrArgument;
+ }
+
+ TVideoPicture *picture = (TVideoPicture *) aInp;
+ if( ( picture->iOptions & TVideoPicture::ETimestamp )
+ && aError != ( KErrCancel ) )
+ {
+ iLastEncodedPictureTimestamp = picture->iTimestamp.Int64();
+ }
+
+ // if custom buffer emabled then add it to queue else return the picture
+ // to client
+ if ( !iInputBufReturnToPreProc )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::InputBufferConsumed()-return picture back to client" ) );
+
+ iMMFDevVideoRecordProxy->MdvrpReturnPicture( picture );
+ }
+ else
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::InputBufferConsumed()-return picture back to Input Device" ) );
+ iInputDevice->ReturnPicture( picture );
+ }
+
+ if ( iInputEndCalled && ( iEngine->NumInputBuffers() == 0 )
+ && ( iCodec->IsCurrentPictureSkipped() ) )
+ {
+ PRINT_MSG( LEVEL_HIGH, ("CAriH264encHwDeviceImpl"
+ "::InputBufferConsumed()::Calling stream end " ) );
+ Stop();
+ iMMFDevVideoRecordProxy->MdvrpStreamEnd();
+ return( KErrNone );
+ }
+
+ PRINT_EXIT;
+ return KErrNone;
+ }
+
+//----------------------------------------------------------------------------
+// Callback to indicate the output buffer is ready
+//----------------------------------------------------------------------------
+//
+
+TInt CAriH264encHwDeviceImpl::OutputBufferReady ( TAny* aOup, TInt aError )
+ {
+ PRINT_ENTRY;
+
+ TVideoOutputBuffer *outputBuf = ( TVideoOutputBuffer* ) aOup;
+ TInt error = KErrNone;
+ TInt length = outputBuf->iData.Length();
+
+ if (iFrozen)
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::OutputBufferReady() "
+ "Frozen state, so drop output picture" ) );
+ outputBuf->iData.Set( ( TUint8* )outputBuf->iData.Ptr()
+ ,iOutputBufferSize );
+ iEngine->AddOutput( outputBuf );
+ return KErrNone;
+ }
+
+ if( aError == KErrNone )
+ {
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ error = iInternalOutputBufferQueue.Append( outputBuf );
+ if ( error != KErrNone )
+ {
+ ClientFatalError ( error );
+ return KErrNone;
+ }
+
+ // get the packet offset infor
+ error = iCodec->GetParam( CONTROL_CMD_GET_PACKET_OFFSET_DATA,
+ iFreeBufferQueueForPacketOffsetInfo[0] );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return KErrNone;
+ }
+
+ //remove the first element and add it to filled Queue
+ TUint* filledOffsetLengthInfoBuffer
+ = iFreeBufferQueueForPacketOffsetInfo[0];
+ iFreeBufferQueueForPacketOffsetInfo.Remove( 0 );
+ error = iFilledBufferQueueForPacketOffsetInfo.Append(
+ filledOffsetLengthInfoBuffer );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return KErrNone;
+ }
+
+ if ( !iTotalLengthFilledSoFarInPacketMode )
+ {
+ iTotalOutputBufferLengthInPacketMode
+ = iInternalOutputBufferQueue[0]->iData.Length();
+ iPacketOffSetCurrentPosition
+ = iFilledBufferQueueForPacketOffsetInfo[0];
+ iPacketsPending = ETrue;
+
+ while ( iOutputFreeBufferQueue.Count() && iPacketsPending )
+ {
+ TVideoOutputBuffer *outBuf = iOutputFreeBufferQueue[0];
+ FillVideoSegment( outBuf, iInternalOutputBufferQueue[0] );
+ iOutputFreeBufferQueue.Remove( 0 );
+
+ #ifdef CALCINSTANTBITRATE
+ CalculateInstantBitRate( *outBuf );
+ #endif
+
+ iMMFDevVideoRecordProxy->MdvrpNewBuffer( outBuf );
+ }
+ }
+ TInt ts
+ = ( TInt ) ( ( outputBuf->iCaptureTimestamp ).Int64() / 1000 );
+ iSizePerFrame = 0;
+ }
+ else
+ {
+ #ifdef CALCINSTANTBITRATE
+ CalculateInstantBitRate( *outputBuf );
+ #endif
+
+ iSizePerFrame = outputBuf->iData.Length();
+ iSizePerFrame = 0 ;
+ // inform devvideo record that the new encoded buffer is
+ // avaibable
+ iMMFDevVideoRecordProxy->MdvrpNewBuffer( outputBuf );
+ }
+ iNoOfOutputFramesPerSec++;
+ }
+
+ else if ( aError == KErrCancel )
+ {
+ // add the buffer back to outputQueue
+ outputBuf->iData.Set( ( TUint8* )outputBuf->iData.Ptr(),
+ iOutputBufferSize );
+
+ if ( iH264EncInitParams.iDataUnitType == EDuVideoSegment )
+ {
+ error = iInternalOutputBufferQueue.Append( outputBuf );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return KErrNone;
+ }
+ }
+ else
+ {
+ error = iOutputFreeBufferQueue.Append( outputBuf );
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return KErrNone;
+ }
+ }
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return KErrNone;
+ }
+ }
+ else
+ {
+ ClientFatalError( aError );
+ return KErrNone;
+ }
+
+ if ( iInputEndCalled && ( iEngine->NumInputBuffers() == 0 ) )
+ {
+ PRINT_MSG( LEVEL_HIGH, ("CAriH264encHwDeviceImpl"
+ "::OutputBufferReady()::Calling stream end " ) );
+ Stop();
+ iMMFDevVideoRecordProxy->MdvrpStreamEnd();
+ return( KErrNone );
+ }
+
+ PRINT_EXIT;
+ return KErrNone;
+ }
+
+//----------------------------------------------------------------------------
+// Callback to indicate the command has been processed
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::CommandProcessed ( TInt aCmd, TAny* aCmdData,
+ TInt aError )
+ {
+ PRINT_ENTRY;
+
+ switch( aCmd )
+ {
+ case CONTROL_CMD_SET_RATE_CONTROL_OPTIONS:
+ {
+ TRateControlOptions *options = ( TRateControlOptions* ) aCmdData;
+ delete options;
+ }
+ break;
+
+ case CONTROL_CMD_SET_FORCED_I_FRAME:
+ {
+ }
+ break;
+
+ case CONTROL_CMD_SET_COMMIT_OPTIONS:
+ {
+ TH264EncInitParams *currentParams
+ = ( TH264EncInitParams* ) aCmdData;
+ if( ( aError != KErrNone ) || ( aError != KErrCancel ) )
+ {
+ delete currentParams;
+ return;
+ }
+ else{
+ iH264EncInitParams.iBitErrors
+ = currentParams->iBitErrors;
+ iH264EncInitParams.iPacketLosses
+ = currentParams->iPacketLosses;
+ iH264EncInitParams.iRandomAccessRate
+ = currentParams->iRandomAccessRate;
+
+ delete currentParams;
+ }
+ }
+ break;
+
+ case CONTROL_CMD_SET_COMPLEXITY_LEVEL:
+ {
+ TH264EncInitParams *currentParams
+ = ( TH264EncInitParams* ) aCmdData;
+ delete currentParams;
+ }
+ break;
+
+ case CONTROL_CMD_SET_CHANNEL_BIT_ERROR_RATE:
+ {
+ TReal* currentParams = ( TReal* )aCmdData;
+ delete currentParams;
+ }
+ break;
+
+ case CONTROL_CMD_SET_SLICELOSS:
+ {
+ TH264EncSliceLoss* currentParams
+ = ( TH264EncSliceLoss* )aCmdData;
+ delete currentParams;
+ }
+ break;
+
+ default:
+ break;
+ }
+ PRINT_EXIT;
+ return;
+ }
+
+//----------------------------------------------------------------------------
+// Called when a fatal error occurs in process engine
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::FatalErrorFromProcessEngine( TInt aError )
+ {
+ PRINT_ENTRY;
+
+ ClientFatalError( aError );
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Enables inserting H324 pre-defined config data (VOL / SPS / PPS / etc. )
+//----------------------------------------------------------------------------
+//
+
+TInt CAriH264encHwDeviceImpl::H324AnnexKDefinedEncoderConfigDataOn()
+ {
+ PRINT_ENTRY;
+
+ if( iEncStateMac->IsInitialized() )
+ {
+ PRINT_MSG( LEVEL_LOW, ("Not permitted as the encoder is already "
+ "initialised" ) );
+ return KErrNotReady;
+ }
+ iH264EncInitParams.iVTFastCallSetUp = ETrue;
+
+ PRINT_EXIT;
+ return KErrNone;
+ }
+
+
+//----------------------------------------------------------------------------
+// 2 phase constructor
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ConstructL()
+ {
+ PRINT_ENTRY;
+
+ TInt error = KErrNone;
+
+ // Create Array of Supported Input Formats
+ TUncompressedVideoFormat inputFormat;
+
+ inputFormat.iDataFormat = EYuvRawData;
+ inputFormat.iYuvFormat.iCoefficients = EYuvBt709Range0;
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma1;
+ inputFormat.iYuvFormat.iDataLayout = EYuvDataPlanar;
+ inputFormat.iYuvFormat.iYuv2RgbMatrix = NULL;
+ inputFormat.iYuvFormat.iRgb2YuvMatrix = NULL;
+ inputFormat.iYuvFormat.iAspectRatioNum = 1;
+ inputFormat.iYuvFormat.iAspectRatioDenom = 1;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma2;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma3;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iCoefficients = EYuvBt709Range1;
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma1;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma2;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma3;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+
+ inputFormat.iYuvFormat.iCoefficients = EYuvBt601Range0;
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma1;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma2;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma3;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iCoefficients = EYuvBt601Range1;
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma1;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma2;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ inputFormat.iYuvFormat.iPattern = EYuv420Chroma3;
+ error = iSupportedInputFormats.Append( inputFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending input format...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Create Array of Supported Output Formats
+ CCompressedVideoFormat* compressedVideoFormat =
+ CCompressedVideoFormat::NewL( KH264MimeType );
+
+ CleanupStack::PushL( compressedVideoFormat );
+ error = iSupportedOutputFormats.Append( compressedVideoFormat );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ // unknown level is set for short mime type - decide in initialize
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_UNKNOWN );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 1
+ CCompressedVideoFormat* compressedVideoFormat2 =
+ CCompressedVideoFormat::NewL( KH264MimeType2 );
+
+ CleanupStack::PushL( compressedVideoFormat2 );
+ error = iSupportedOutputFormats.Append( compressedVideoFormat2 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_1 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 1.1
+ // Bitrate and level will be decided in Initialize
+ CCompressedVideoFormat* compressedVideoFormat3 =
+ CCompressedVideoFormat::NewL( KH264MimeType3 );
+
+ CleanupStack::PushL( compressedVideoFormat3 );
+ error = iSupportedOutputFormats.Append( compressedVideoFormat3 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_11 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 1.2
+ CCompressedVideoFormat* compressedVideoFormat4 =
+ CCompressedVideoFormat::NewL( KH264MimeType4 );
+
+ CleanupStack::PushL( compressedVideoFormat4 );
+ error = iSupportedOutputFormats.Append( compressedVideoFormat4 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_12 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 1.3
+ CCompressedVideoFormat* compressedVideoFormat5 =
+ CCompressedVideoFormat::NewL( KH264MimeType5 );
+
+ CleanupStack::PushL( compressedVideoFormat5 );
+ error = iSupportedOutputFormats.Append( compressedVideoFormat5 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_13 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 2
+ CCompressedVideoFormat* compressedVideoFormat6 =
+ CCompressedVideoFormat::NewL( KH264MimeType6 );
+
+ CleanupStack::PushL( compressedVideoFormat6 );
+
+ error = iSupportedOutputFormats.Append( compressedVideoFormat6 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_2 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 2.1
+ CCompressedVideoFormat* compressedVideoFormat7 =
+ CCompressedVideoFormat::NewL( KH264MimeType7 );
+
+ CleanupStack::PushL( compressedVideoFormat7 );
+
+ error = iSupportedOutputFormats.Append( compressedVideoFormat7 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_21 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 2.2
+ CCompressedVideoFormat* compressedVideoFormat8 =
+ CCompressedVideoFormat::NewL( KH264MimeType8 );
+
+ CleanupStack::PushL( compressedVideoFormat8 );
+
+ error = iSupportedOutputFormats.Append( compressedVideoFormat8 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_22 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 3
+ CCompressedVideoFormat* compressedVideoFormat9 =
+ CCompressedVideoFormat::NewL( KH264MimeType9 );
+
+ CleanupStack::PushL( compressedVideoFormat9 );
+
+ error = iSupportedOutputFormats.Append( compressedVideoFormat9 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_3 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ // Level 1b
+ CCompressedVideoFormat* compressedVideoFormat10 =
+ CCompressedVideoFormat::NewL( KH264MimeType10 );
+
+ CleanupStack::PushL( compressedVideoFormat10 );
+
+ error = iSupportedOutputFormats.Append( compressedVideoFormat10 );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output format...leaving \n" );
+ User::Leave( error );
+ }
+ CleanupStack::Pop();
+
+ error = iLevels.Append( KH264ENCIMPL_LEVEL_1b );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending supported level...leaving \n" );
+ User::Leave( error );
+ }
+
+ iPeriodicTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+ iOutputFreeBufferQueue.Reset();
+ iInternalOutputBufferQueue.Reset();
+ iEncStateMac = CStateMachine::NewL();
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sends the updated time to the codec
+//----------------------------------------------------------------------------
+//
+TInt CAriH264encHwDeviceImpl::UpdateTime()
+ {
+ PRINT_ENTRY;
+
+ if ( !iClockSource )
+ {
+ ClientFatalError( KErrBadHandle );
+ return -1;
+ }
+
+ // send the time values to the codec
+ iCodec->SetUpdatedRefernceTime( iTotalTime );
+
+ PRINT_EXIT;
+ return 1;
+ }
+
+//----------------------------------------------------------------------------
+// Create the output buffers in Coded picture mode
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::CreateCodedOutputBuffersL( TUint aSize )
+ {
+ PRINT_ENTRY;
+
+ if( iH264EncInitParams.iDataUnitType != EDuVideoSegment )
+ {
+ iOutputBufferSize = aSize;
+ }
+
+ // Allocate memory for TVideoOutputBuffer
+ iOutputBuffers = new ( ELeave ) TVideoOutputBuffer[
+ iH264EncInitParams.iMinNumOutputBuffers];
+
+ for ( TInt i = 0; i < iH264EncInitParams.iMinNumOutputBuffers; i++ )
+ {
+ iOutputBuffers[i].iData.Set( NULL, 0);
+ }
+
+ // Create the Buffer and add it to Queue
+ for ( TInt i = 0; i < iH264EncInitParams.iMinNumOutputBuffers; i++ )
+ {
+ TUint8* ptr = new ( ELeave ) TUint8[aSize];
+ CleanupStack::PushL( ptr );
+ iOutputBuffers[i].iData.Set( ptr, aSize );
+ CleanupStack::Pop();
+ InitializeOuputCodedBuffer( iOutputBuffers[i] );
+ TInt error = iOutputFreeBufferQueue.Append( iOutputBuffers + i );
+ if ( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending output buffer to the"
+ "output buffer queue \n" );
+ User::Leave( error );
+ return;
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Creates the temporary output buffers
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::CreateInternalOutputBuffersL(
+ TUint aBufferSize )
+ {
+ PRINT_ENTRY;
+
+ iOutputBufferSize = aBufferSize;
+
+ // Allocate memory for TVideoOutputBuffer
+ iInternalOutputBuffers = new ( ELeave ) TVideoOutputBuffer[
+ KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS];
+
+ for ( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ iInternalOutputBuffers[i].iData.Set( NULL, 0 );
+ }
+
+ // Create the Buffer and add it to Queue
+ for ( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ TUint8* ptr = new ( ELeave ) TUint8[aBufferSize];
+ CleanupStack::PushL( ptr );
+ iInternalOutputBuffers[i].iData.Set( ptr, aBufferSize );
+ CleanupStack::Pop();
+ InitializeOuputCodedBuffer( iInternalOutputBuffers[i] );
+ TInt error
+ = iInternalOutputBufferQueue.Append( iInternalOutputBuffers + i );
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Creates the buffers required to store length and offset
+// info of packets
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::CreatePacketOffsetLengthInfoBuffersL(
+ TUint aNumOfPackets )
+ {
+ PRINT_ENTRY;
+
+ iPacketOffSetAndLengthInfoBuffers = new ( ELeave )
+ ( TUint*[KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS] );
+
+ for ( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ iPacketOffSetAndLengthInfoBuffers[i] = NULL;
+ }
+
+ for ( TInt i = 0; i < KH264ENCIMPL_MAXNUM_TEMPOUTPUTBUFFERS; i++ )
+ {
+ iPacketOffSetAndLengthInfoBuffers[i] = ( TUint* ) ( new ( ELeave )
+ TUint8[aNumOfPackets] );
+ TInt error = iFreeBufferQueueForPacketOffsetInfo.Append(
+ iPacketOffSetAndLengthInfoBuffers[i] );
+ if( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending packet lengthoffset buffer to "
+ "queue \n" );
+ User::Leave( error );
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// decides whether picture can be encoded or not
+//----------------------------------------------------------------------------
+//
+TBool CAriH264encHwDeviceImpl::CanEncode( TVideoPicture *aPicture )
+ {
+ PRINT_ENTRY;
+
+ // check with the last encoded picture and decide whether it can be
+ // processed or skipped
+ if( aPicture->iTimestamp.Int64() < iLastEncodedPictureTimestamp )
+ {
+ return EFalse;
+ }
+
+ // check with current clock
+ if( ( aPicture->iTimestamp.Int64() ) < ( ( iClockSource->Time().Int64() -
+ iTotalTime ) + KH264ENCIMPL_ENCODEAHEAD ) )
+ {
+ return EFalse;
+ }
+
+ PRINT_EXIT;
+ return ETrue;
+ }
+//----------------------------------------------------------------------------
+// Skips the Input Picture
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::SkipInputPicture( TVideoPicture *aPicture )
+ {
+
+ PRINT_ENTRY;
+
+ // add the buffer back to queue
+ if ( !iInputBufReturnToPreProc )
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::SkipInputPicture()"
+ "-return picture back to client" ) );
+ iMMFDevVideoRecordProxy->MdvrpReturnPicture( aPicture );
+ }
+ else
+ {
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::SkipInputPicture()-"
+ "return picture back to Input Device" ) );
+ iInputDevice->ReturnPicture( aPicture );
+ }
+
+ if ( !iFrozen )
+ {
+ iPictureCounters.iPicturesSkippedRateControl++;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Indicates whether the next frame is to be encoded as an I frame
+//----------------------------------------------------------------------------
+//
+TBool CAriH264encHwDeviceImpl::IsForcedIFrameRequired(
+ TVideoPicture* aPicture )
+ {
+ PRINT_ENTRY;
+
+ if( ( aPicture->iOptions & TVideoPicture::EReqInstantRefresh ) ||
+ iPictureLoss )
+ {
+ PRINT_MSG( LEVEL_HIGH, ("CAriH264encHwDeviceImpl"
+ "::IsForcedIFrameRequired() ETrue 1--" ) );
+ return ETrue;
+ }
+
+ PRINT_EXIT;
+ return EFalse;
+ }
+
+//----------------------------------------------------------------------------
+// Extracts 1 packet from a frame and Fills output buffer with the same
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::FillVideoSegment(
+ TVideoOutputBuffer* aOutputBuf, TVideoOutputBuffer* aSrcOutputBuf )
+ {
+ PRINT_ENTRY;
+
+ // first time fill all config information in one o/p buffer
+ if ( iIsConfigDataFilledInFirstOutputBuffer )
+ {
+ TUint configDataLength = 0;
+ TUint* startPtr = iPacketOffSetCurrentPosition;
+ TInt noOfConfigParamas = 0;
+
+#ifdef EMZ_AVC_ENC_CODEC_SEIINFO_ENABLE
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::FillVideoSegment() "
+ "SEI enabled" ) );
+ noOfConfigParamas= KNumOfConfigParams_SEI;
+#else
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::FillVideoSegment() "
+ "SEI disabled" ) );
+ noOfConfigParamas= KNumOfConfigParams;
+#endif
+ for( TInt i = 0; i < noOfConfigParamas; i++ )
+ {
+ configDataLength += * ( ++startPtr ) ++;
+ }
+
+ // copy data into output buffer
+ Mem::Copy( ( TUint8* )( ( TUint8* )aOutputBuf->iData.Ptr() ),
+ ( TUint8* )( aSrcOutputBuf->iData.Ptr() ), configDataLength );
+
+ iTotalLengthFilledSoFarInPacketMode += configDataLength;
+
+ if( iH264EncInitParams.iDataEncapsulation == EDuGenericPayload )
+ {
+
+ // word boundary calculation
+ TUint32 offset = ( TUint32 )( ( TUint8* )aOutputBuf->iData.Ptr()
+ + configDataLength );
+
+ if ( offset % KWordLength )
+ {
+ offset = KWordLength - ( offset % KWordLength );
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ configDataLength += offset;
+ TUint8* ptr = ( ( TUint8* )aOutputBuf->iData.Ptr()
+ + configDataLength );
+
+ // copy offset and length information
+ Mem::Copy( ptr, ( TUint8* )iPacketOffSetCurrentPosition,
+ ( noOfConfigParamas*KDoubleWordLength ) );
+
+ ptr += ( noOfConfigParamas * KDoubleWordLength );
+
+ //put the num of nal units information
+ TUint* nalInfo = ( TUint* )ptr;
+ nalInfo[0] = noOfConfigParamas;
+
+ configDataLength += ( ( noOfConfigParamas*KDoubleWordLength ) +
+ KWordLength );
+ }
+
+ // increment the packet offsetpointer
+ iPacketOffSetCurrentPosition += ( noOfConfigParamas * 2 );
+ aOutputBuf->iData.Set( aOutputBuf->iData.Ptr(),configDataLength );
+ iIsConfigDataFilledInFirstOutputBuffer = EFalse;
+ }
+ else
+ {
+ TUint currentPacketLength = *( ++iPacketOffSetCurrentPosition );
+
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl::FillVideoSegment()"
+ " currentPacketLength is %d", ( TInt )currentPacketLength ) );
+
+ if ( iTotalLengthFilledSoFarInPacketMode
+ < iTotalOutputBufferLengthInPacketMode )
+ {
+ Mem::Copy( ( TUint8* )( aOutputBuf->iData.Ptr() ),
+ ( TUint8* )( aSrcOutputBuf->iData.Ptr() +
+ iTotalLengthFilledSoFarInPacketMode ), currentPacketLength );
+
+ aOutputBuf->iData.Set( aOutputBuf->iData.Ptr(),
+ currentPacketLength );
+
+ iTotalLengthFilledSoFarInPacketMode
+ = iTotalLengthFilledSoFarInPacketMode + currentPacketLength;
+
+ if ( iH264EncInitParams.iDataEncapsulation == EDuGenericPayload )
+ {
+ // fill the offset and length information
+ TUint32 offset = ( TUint32 )( aOutputBuf->iData.Ptr()
+ + currentPacketLength );
+
+ if ( offset % KWordLength )
+ {
+ offset = ( KWordLength - ( offset % KWordLength ) );
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ TUint* ptr = ( TUint* ) ( aOutputBuf->iData.Ptr()
+ + currentPacketLength + offset );
+
+ ptr[0] = 0;
+ ptr[1] = *( iPacketOffSetCurrentPosition );
+ ptr[2] = 1;
+
+ aOutputBuf->iData.Set( aOutputBuf->iData.Ptr(),
+ currentPacketLength + offset + KDoubleWordLength
+ + KWordLength );
+ }
+
+ if ( iTotalLengthFilledSoFarInPacketMode ==
+ iTotalOutputBufferLengthInPacketMode )
+ {
+ iTotalLengthFilledSoFarInPacketMode = 0;
+ iPacketsPending = EFalse;
+
+ // remove packet offset info buffer from filled Q and
+ // add it to free Q
+ TUint* freeOffsetLengthInfoBuffer
+ = iFilledBufferQueueForPacketOffsetInfo[0];
+
+ iFilledBufferQueueForPacketOffsetInfo.Remove( 0 );
+ TInt error = iFreeBufferQueueForPacketOffsetInfo.Append(
+ freeOffsetLengthInfoBuffer );
+
+ if ( error != KErrNone )
+ {
+ ClientFatalError( error );
+ return;
+ }
+
+ // Remove the internal buffer and add it back to process
+ // engine
+ if ( iInternalOutputBufferQueue.Count() )
+ {
+ TVideoOutputBuffer* outBuf
+ = iInternalOutputBufferQueue[0];
+ iInternalOutputBufferQueue.Remove( 0 );
+ outBuf->iData.Set( ( TUint8* )outBuf->iData.Ptr(),
+ iOutputBufferSize );
+
+ // Add the Buffer back to the Process Engine
+ if( ( !iEncStateMac->IsInputEndPending() ) &&
+ ( !iEncStateMac->IsStopped() ) )
+ {
+ iEngine->AddOutput( ( TAny* )outBuf );
+ }
+ }
+
+ // Still more encoded packets are available
+ if( iInternalOutputBufferQueue.Count() )
+ {
+ iPacketsPending = ETrue;
+ iTotalOutputBufferLengthInPacketMode
+ = iInternalOutputBufferQueue[0]->iData.Length();
+
+ // Get the packet offset info buffer
+ if( iFilledBufferQueueForPacketOffsetInfo.Count() )
+ {
+ iPacketOffSetCurrentPosition
+ = iFilledBufferQueueForPacketOffsetInfo[0];
+ }
+ }
+ }
+ else
+ {
+ ++iPacketOffSetCurrentPosition;
+ }
+ }
+ }
+
+ // Update the specific members of the output buffer
+ aOutputBuf->iRequiredSeveralPictures
+ = aSrcOutputBuf->iRequiredSeveralPictures;
+ aOutputBuf->iRandomAccessPoint = aSrcOutputBuf->iRandomAccessPoint;
+ aOutputBuf->iCaptureTimestamp = aSrcOutputBuf->iCaptureTimestamp;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Initializes the members of the output coded buffers created
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::InitializeOuputCodedBuffer(
+ TVideoOutputBuffer& aOutputBuffer )
+ {
+ PRINT_ENTRY;
+
+ aOutputBuffer.iOrderNumber = 0;
+ aOutputBuffer.iMinErrorProtectionLevel = 1;
+ aOutputBuffer.iMaxErrorProtectionLevel = 1;
+ aOutputBuffer.iRequiredThisPicture = EFalse;
+ aOutputBuffer.iLayer = 0;
+ aOutputBuffer.iInLayerScalabilityStep = 0;
+ aOutputBuffer.iDataPartitionNumber = 0;
+ aOutputBuffer.iHrdVbvParams.Set( NULL, 0 );
+ aOutputBuffer.iCodingStandardSpecificData.Set( NULL, 0 );
+ aOutputBuffer.iImplementationSpecificData.Set( NULL, 0 );
+
+ // The following members will be modified later during execution
+ aOutputBuffer.iRequiredSeveralPictures = EFalse;
+ aOutputBuffer.iRandomAccessPoint = EFalse;
+ aOutputBuffer.iCaptureTimestamp = 0;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Sets level and bitrate based on size information
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::SetLevelAndBitRate()
+ {
+ PRINT_ENTRY;
+
+ if( (iH264EncInitParams.iPictureSize.iWidth <= KH264ENCIMPL_QCIF_WIDTH )
+ && ( iH264EncInitParams.iPictureSize.iHeight
+ <= KH264ENCIMPL_QCIF_HEIGHT ) )
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_1;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_1;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ }
+ //QVGA
+ else
+ if( ( iH264EncInitParams.iPictureSize.iWidth
+ <= KH264ENCIMPL_QVGA_WIDTH ) &&
+ ( iH264EncInitParams.iPictureSize.iHeight
+ <= KH264ENCIMPL_QVGA_HEIGHT ) )
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_12;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_12;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ }
+ //CIF
+ else
+ if( ( iH264EncInitParams.iPictureSize.iWidth
+ <= KH264ENCIMPL_CIF_WIDTH ) &&
+ ( iH264EncInitParams.iPictureSize.iHeight
+ <= KH264ENCIMPL_CIF_HEIGHT ) )
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_13;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_13;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate30;
+ }
+ // VGA
+ else
+ if( ( iH264EncInitParams.iPictureSize.iWidth
+ <= KH264ENCIMPL_VGA_WIDTH ) &&
+ ( iH264EncInitParams.iPictureSize.iHeight
+ <= KH264ENCIMPL_VGA_HEIGHT ) )
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_22;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_22;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate15;
+ }
+ else
+ {
+ iH264EncInitParams.iLevel = KH264ENCIMPL_LEVEL_3;
+ iH264EncInitParams.iBitRate = KH264ENCIMPL_BITRATE_LEVEL_3;
+ iH264EncInitParams.iTargetPictureRate = KPictureRate25;
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Checks if the specified input format is supported or not
+//----------------------------------------------------------------------------
+//
+TBool CAriH264encHwDeviceImpl::CheckInputFormat(
+ const TUncompressedVideoFormat& aFormat )
+ {
+ PRINT_ENTRY;
+
+ // Check if encoder supports the passed input format
+ if ( aFormat.iDataFormat != EYuvRawData )
+ {
+ return EFalse;
+ }
+
+ if ( aFormat.iYuvFormat.iDataLayout != EYuvDataPlanar )
+ {
+ PRINT_EXIT;
+ return EFalse;
+ }
+
+ if ( ( aFormat.iYuvFormat.iCoefficients != EYuvBt709Range0 ) &&
+ ( aFormat.iYuvFormat.iCoefficients != EYuvBt709Range1 ) &&
+ ( aFormat.iYuvFormat.iCoefficients != EYuvBt601Range0 ) &&
+ ( aFormat.iYuvFormat.iCoefficients != EYuvBt601Range1 ) )
+ {
+ return EFalse;
+ }
+
+ if ( ( aFormat.iYuvFormat.iPattern != EYuv420Chroma1 ) &&
+ ( aFormat.iYuvFormat.iPattern != EYuv420Chroma2 ) &&
+ ( aFormat.iYuvFormat.iPattern != EYuv420Chroma3 ) )
+ {
+ return EFalse;
+ }
+
+ PRINT_EXIT;
+ return ETrue;
+ }
+
+
+//----------------------------------------------------------------------------
+// Nofities the client that the fatal error happend in Hw device
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ClientFatalError( TInt aError )
+ {
+ PRINT_ENTRY;
+ PRINT_MSG( LEVEL_CRITICAL, ("CAriH264encHwDeviceImpl::ClientFatalError()"
+ " Error is %d", aError ) );
+
+ if( iClockSource )
+ {
+ iPeriodicTimer->Cancel();
+ }
+
+ // Stop processing
+ if( !iEncStateMac->IsStopped() )
+ {
+ if( iEncStateMac->IsInitialized() )
+ {
+ Stop();
+ }
+ }
+ iEncStateMac->Transit( CStateMachine::EDeadStateCommand );
+ iMMFDevVideoRecordProxy->MdvrpFatalError( this, aError );
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Output buffers are created with the specified size
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::ReallocSegmentOutputBuffersL( TUint aSize )
+ {
+ PRINT_ENTRY;
+
+ TInt count = iOutputFreeBufferQueue.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ // dellallocate memory for this buffer
+ TVideoOutputBuffer* ouputBuf = iOutputFreeBufferQueue[i];
+ if ( ouputBuf->iData.Ptr() )
+ {
+ delete ( TUint8* )ouputBuf->iData.Ptr();
+ }
+
+ // and allocate memory and store it in temp Q
+ TUint8* ptr = new ( ELeave ) TUint8[aSize];
+ CleanupStack::PushL( ptr );
+ ouputBuf->iData.Set( ptr, aSize );
+ CleanupStack::Pop();
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Reallocates single buffer
+//----------------------------------------------------------------------------
+//
+void CAriH264encHwDeviceImpl::ReallocateSegmentBufferL(
+ TVideoOutputBuffer* aBuffer )
+ {
+ PRINT_ENTRY;
+
+ TInt size = iH264EncInitParams.iMaxCodedSegmentSize;
+ if( iH264EncInitParams.iDataEncapsulation == EDuGenericPayload )
+ {
+ size += KDoubleWordLength + KWordLength;
+ }
+
+ if ( aBuffer->iData.Ptr() )
+ {
+ delete ( TUint8* )aBuffer->iData.Ptr();
+ }
+
+ // and allocate memory and store it in temp Q
+ TUint8* ptr = new ( ELeave ) TUint8[size];
+ CleanupStack::PushL( ptr );
+ aBuffer->iData.Set( ptr, ( size ) );
+ CleanupStack::Pop();
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Creates single buffer for frame mode to packet mode change
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::CreateCodedBufferForModeChangeL()
+ {
+ PRINT_ENTRY;
+
+ iCodedBufferForPacketModeChange = new ( ELeave ) TVideoOutputBuffer;
+ TUint8* ptr = new ( ELeave ) TUint8[iOutputBufferSize];
+ CleanupStack::PushL( ptr );
+ iCodedBufferForPacketModeChange->iData.Set( ptr, iOutputBufferSize );
+ CleanupStack::Pop();
+ InitializeOuputCodedBuffer( *iCodedBufferForPacketModeChange );
+
+ PRINT_EXIT;
+ }
+
+
+//----------------------------------------------------------------------------
+// Creates buffers which are used as output buffers in packet mode. Function
+// is called only when frame mode - packet mode change occurs while encoding
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::CreateSegmentOutputBuffersL(
+ TUint aNumOfBuffers, TUint aSize )
+ {
+ PRINT_ENTRY;
+
+ TInt segmentSize = aSize;
+ // 4+4 bytes for offset and length
+ if( iH264EncInitParams.iDataEncapsulation == EDuGenericPayload )
+ {
+ segmentSize += KDoubleWordLength + KWordLength;
+ }
+
+ // Allocate memory for TVideoOutputBuffer
+ iSegmentBuffers = new ( ELeave ) TVideoOutputBuffer[aNumOfBuffers];
+ for ( TInt i = 0; i < aNumOfBuffers; i++ )
+ {
+ iSegmentBuffers[i].iData.Set( NULL, 0 );
+ }
+
+ // Create the Buffer and add it to Queue
+ for ( TInt i = 0; i < aNumOfBuffers; i++ )
+ {
+ TUint8* ptr = new ( ELeave ) TUint8[segmentSize];
+ CleanupStack::PushL( ptr );
+ iSegmentBuffers[i].iData.Set( ptr, segmentSize );
+ CleanupStack::Pop();
+ InitializeOuputCodedBuffer( iSegmentBuffers[i] );
+ TInt error = iOutputFreeBufferQueue.Append( iSegmentBuffers + i );
+ if ( error != KErrNone )
+ {
+ PRINT_ERR( "Error while appending segment output buffer to the"
+ "segment output buffer queue" );
+ User::Leave( error );
+ return;
+ }
+ }
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// Calculates the instant bit rate
+//----------------------------------------------------------------------------
+//
+
+void CAriH264encHwDeviceImpl::CalculateInstantBitRate(
+ const TVideoOutputBuffer &aOutBuf )
+ {
+ PRINT_ENTRY;
+
+ TInt size = 0;
+ TReal ts = ( ( aOutBuf.iCaptureTimestamp ).Int64() ) / 1000000.0;
+ size = aOutBuf.iData.Length();
+ TInt32 partInt = 0;
+ Math::Int( partInt, ts );
+
+ // Calculate stream size, averaged per 1 second
+ if ( partInt > iCurrentIntTS )
+ {
+ #ifdef DEBUG_INFO
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::CalculateInstantBitRate(), Stream size per 1 second: %d",
+ iStreamSize * 8 ) );
+ PRINT_MSG( LEVEL_LOW, ("CAriH264encHwDeviceImpl"
+ "::CalculateInstantBitRate(), Number of frames per 1 second: "
+ " %d", iNoOfOutputFramesPerSec ) );
+ #endif
+ // Reset global stream size
+ iStreamSize = 0;
+ iNoOfOutputFramesPerSec = 0;
+ iCurrentIntTS = partInt;
+ }
+ iSizePerFrame = iSizePerFrame + size;
+ iStreamSize = iStreamSize + size;
+
+ PRINT_EXIT;
+ }
+
+//----------------------------------------------------------------------------
+// The implementation table entry which indicates the 1st function
+// to call when H264 encoder hwdevice plugin is selected
+//----------------------------------------------------------------------------
+//
+const TImplementationProxy ImplementationTable[] =
+ {
+ { KUidH264EncoderHwDeviceImplUid,
+ ( TProxyNewLPtr )( CAriH264encHwDeviceImpl::NewL ) }
+ };
+
+//----------------------------------------------------------------------------
+// Returns the implementation table
+//----------------------------------------------------------------------------
+//
+
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(
+ TInt& aTableCount )
+{
+ aTableCount = sizeof( ImplementationTable )
+ / sizeof( TImplementationProxy );
+ return ImplementationTable;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+