diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccredpayloadformat/src/mccredencoder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmccredpayloadformat/src/mccredencoder.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,231 @@ +/* +* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Encoder implementation capable to form redundancy RTP payload. +* +*/ + + + + + +// INCLUDE FILES +#include "mccredencoder.h" +#include "streamformatter.h" +#include "mccredpayloadformatdefs.h" +#include "mccdef.h" + +// CONSTANTS +const TUint KPrimaryEncPTInd = 0; + +// ============================= LOCAL FUNCTIONS =============================== + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMccRedEncoder::CMccRedEncoder +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMccRedEncoder::CMccRedEncoder() + { + DP_RED_ENCODE( "CMccRedEncoder::CMccRedEncoder" ) + } + +// ----------------------------------------------------------------------------- +// CMccRedEncoder::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMccRedEncoder::ConstructL() + { + DP_RED_ENCODE( "CMccRedEncoder::ConstructL" ) + + iRedHeaders + = HBufC8::NewL( KDefRedCount * KRedHeaderSize + KFinalHeaderSize ); + } + +// ----------------------------------------------------------------------------- +// CMccRedEncoder::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMccRedEncoder* CMccRedEncoder::NewL() + { + DP_RED_ENCODE( "CMccRedEncoder::NewL" ) + + CMccRedEncoder* self = new( ELeave ) CMccRedEncoder; + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +CMccRedEncoder::~CMccRedEncoder() + { + DP_RED_ENCODE( "CMccRedEncoder::~CMccRedEncoder" ) + + iRedTimeStamps.Close(); + delete iRedHeaders; + delete iRedPayload; + } + + +// ----------------------------------------------------------------------------- +// CMCCRedEncoder::DoInitializeL +// Initialize encoder after encoding parameters are changed or encoding is +// started again after pause. +// ----------------------------------------------------------------------------- +// +void CMccRedEncoder::DoInitializeL( TInt aRedBlockCount, TInt aMaxPayloadSize, + TInt /*aNumOfEncodings*/ ) + { + DP_RED_ENCODE( "CMccRedEncoder::DoInitializeL" ) + + if ( KMaxRedCount < aRedBlockCount || 0 > aRedBlockCount ) + { + User::Leave( KErrArgument ); + } + + if ( KDefRedCount != aRedBlockCount ) + { + delete iRedHeaders; + iRedHeaders = NULL; + iRedHeaders = HBufC8::NewL( + aRedBlockCount * KRedHeaderSize + KFinalHeaderSize ); + } + + // Memory for redundant payloads without redundancy headers + TInt redPayloadSize( aRedBlockCount * aMaxPayloadSize ); + if ( iRedPayload ) + { + if ( iRedPayload->Data().MaxSize() < redPayloadSize ) + { + delete iRedPayload; + iRedPayload = NULL; + iRedPayload = CMMFDataBuffer::NewL( redPayloadSize ); + } + } + else + { + iRedPayload = CMMFDataBuffer::NewL( redPayloadSize ); + } + + iRedPackets = EFalse; + iRedTimeStamps.Reset(); + iRedHeaders->Des().Zero(); + } + + +// ----------------------------------------------------------------------------- +// CMccRedEncoder::EncodePayloadL +// Encode payloads set with SetEncoding() -method. +// ----------------------------------------------------------------------------- +// +void CMccRedEncoder::EncodePayloadL( TUint aCurTimeStamp ) + { + DP_RED_ENCODE( "CMccRedEncoder::EncodePayload" ) + __ASSERT_ALWAYS( iRTPPayload, User::Leave( KErrNotReady ) ); + + TDes8& rtpPayload = iRTPPayload->Data(); + rtpPayload.Zero(); + + // Copy redundant payload if exist + if ( iRedPackets ) + { + rtpPayload.Append( iRedPayload->Data() ); + } + + // Append new payload to the end of redundancy RTP payload + rtpPayload.Append( iEncodings[EMccPrimaryEncoding]->Data() ); + iRedTimeStamps.AppendL( aCurTimeStamp ); + + ConstructRedHeaders( aCurTimeStamp ); + rtpPayload.Insert( 0, *iRedHeaders ); + + // Save redundant data block + iRedPayload->Data().Copy( iEncodings[EMccPrimaryEncoding]->Data() ); + iRedPackets = ETrue; + } + + +// ----------------------------------------------------------------------------- +// CMccRedEncoder::ConstructRedHeaders +// Construct redundancy headers. +// ----------------------------------------------------------------------------- +// +void CMccRedEncoder::ConstructRedHeaders( TUint aCurTimeStamp ) + { + DP_RED_ENCODE( "CMccRedEncoder::ConstructRedHeaders" ) + + // Construct redundancy headers, final header is one byte long + iRedHeaders->Des().Zero(); + const TUint8* seekPtr = iRedHeaders->Ptr(); + + TStreamEncoder streamEncoder; + streamEncoder.Initialize( const_cast( seekPtr ), 0, 0 ); + + // Encode headers except final header + if ( 1 < iRedTimeStamps.Count() ) + { + iRedHeaders->Des().SetLength( + iRedBlockCount * KRedHeaderSize + KFinalHeaderSize ); + + for ( TInt i = 0; i < iRedBlockCount; i++ ) + { + // F-bit + streamEncoder.Encode( 1, KFBitLength ); + // PT + streamEncoder.Encode( iPayloadTypes[KPrimaryEncPTInd], KPTFieldBits ); + // Calculate timestamp offset + TUint offset = aCurTimeStamp - iRedTimeStamps[i]; + // Timestamp offset + streamEncoder.Encode( offset, KTSOffsetBits ); + // Block length + streamEncoder.Encode( iRedPayload->Data().Length(), KBlockLengthBits ); + + DP_RED_ENCODE6( "ENC RED_HEADER NUM %d: F:%d PT:%d TIMESTAMP:%d, BL:%d", + i, ETrue, iPayloadTypes[KPrimaryEncPTInd], iRedTimeStamps[i], + iRedPayload->Data().Length() ) + } + } + else + { + iRedHeaders->Des().SetLength( KFinalHeaderSize ); + } + + // Encode final header + streamEncoder.Encode( 0, KFinalHeaderSize ); + streamEncoder.Encode( iPayloadTypes[KPrimaryEncPTInd], KPTFieldBits ); + + DP_RED_ENCODE5( "ENC FINAL RED_HEADER %d: F:%d PT:%d #TIMESTAMP#:%d", + iRedBlockCount, 0, iPayloadTypes[KPrimaryEncPTInd], aCurTimeStamp ) + + // Delete oldest time stamp + if ( iRedTimeStamps.Count() > iRedBlockCount ) + { + iRedTimeStamps.Remove( 0 ); + } + } + + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + + +// End of File