--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccavcpayloadformat/src/rfc3984encode.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,595 @@
+/*
+* Copyright (c) 2005 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: AVC Payloadization class
+*
+*/
+
+
+
+
+// ============================ INCLUDES =======================================
+
+#include"rfc3984encode.h"
+#include "mccinternalcodecs.h"
+#include <es_sock.h>
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::CRFC3984Encode()
+// Default Constructor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CRFC3984Encode::CRFC3984Encode()
+ {
+ iBufferIndex = 0;
+ iToPayloadizeCount = 0;
+ iNalCount = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::~CRFC3984Encode()
+// Default Destructor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CRFC3984Encode::~CRFC3984Encode()
+ {
+ ClearNalBuffers();
+ iToPayloadizeBuffer.Reset( );
+ iToPayloadizeSizeBuffer.Reset( );
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::NewL()
+// First stage constructor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+CRFC3984Encode * CRFC3984Encode::NewL()
+ {
+ CRFC3984Encode * self = new(ELeave) CRFC3984Encode;
+ CleanupStack::PushL( self );
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::SetMTUSize()
+// Purpose :
+// Parameters :
+// Return Value:
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::SetMTUSize( TUint32 aMtuSize )
+ {
+ iMaxPacketSize = aMtuSize;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::SetFrameRate()
+// Purpose :
+// Parameters :
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::SetFrameRate( TInt aFrameRate )
+ {
+ iFrameRate = aFrameRate;
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::PayloadizeFrameL()
+// Purpose : This function receives the encoded frame and payloadizes it based
+// on the packetization_mode value
+// Parameters : aBuffer - Buffer containing the encoded frame
+// aTimeStamp - Timestamp to go into RTP
+// aMarkerBit - Marker Bit indication (this function sets it for key frames)
+// aNalCount - Reference to return the number of NAL units payloadized
+// Return Value: none, leaves if an error occured
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::PayloadizeFrameL(
+ TDes8 & aBuffer,
+ TUint32 aTimeStamp,
+ TUint32 & aMarkerBit,
+ TInt &aNalCount )
+ {
+ TInt error = KErrNone;
+
+ if ( iPacketizationMode == AVC_MODE_SNALU )
+ {
+ TRAP( error,
+ PayloadizeFrameSingleNALModeL( aBuffer, aTimeStamp, aMarkerBit, aNalCount ) );
+ }
+ else if ( iPacketizationMode == AVC_MODE_NONINTERLEAVED )
+ {
+ TRAP( error,
+ PayloadizeFrameNonInterleavedModeL( aBuffer, aTimeStamp, aMarkerBit, aNalCount ) );
+ }
+ else if ( iPacketizationMode == AVC_MODE_INTERLEAVED )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ if ( KErrNone != error )
+ {
+ ClearNalBuffers();
+ iToPayloadizeBuffer.Reset();
+ iToPayloadizeSizeBuffer.Reset();
+ iToPayloadizeCount = 0;
+ User::Leave( error );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::PayloadizeFrameSingleNALModeL()
+// Purpose : This function receives the encoded frame and payloadizes it
+// according to the SNALU mode
+// Parameters : aBuffer - Buffer containing the encoded frame
+// aTimeStamp - Timestamp to go into RTP
+// aMarkerBit - Marker Bit indication (this function sets it for key frames)
+// aNalCount - This function returns the number of packetized NAL
+// units through this variable.
+// Return Value: none, leaves if an error occured
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::PayloadizeFrameSingleNALModeL(
+ TDes8& aBuffer,
+ TUint32 /*aTimeStamp*/,
+ TUint32& /*aMarkerBit*/,
+ TInt& aNalCount )
+ {
+ // This implementation assumes the NAL units for one frame are seperated
+ // by 0x001 or 0x0001 start codes
+
+ // Resetting iBufferIndex for this new frame, always do this for new frame
+ // because this is used to find start codes within one frame
+ iBufferIndex = 0;
+
+ TInt startIndex = 0; // holds first byte-index of NALU
+ TInt endIndex = 0; // hold byte-index of next to last byte of NALU
+ TInt size = 0;
+ HBufC8 * pBuffer = 0;
+
+ // loop to find and packetize all NAL Units in the frame
+ while ( ETrue )
+ {
+ startIndex = TMccCodecInfo::FindAvcNaluStart( iBufferIndex, aBuffer );
+ if ( KErrNotFound == startIndex )
+ {
+ break;
+ }
+
+ endIndex = TMccCodecInfo::FindAvcNaluEnd( iBufferIndex, aBuffer );
+ if ( KErrNotFound == endIndex )
+ {
+ break;
+ }
+
+ if ( startIndex == endIndex )
+ {
+ break;
+ }
+
+ // finding size of the NAL unit
+ size = endIndex - startIndex;
+
+ __ASSERT_ALWAYS( size > 0, User::Leave( KErrGeneral ) ); // some flaw in logic
+
+ pBuffer = HBufC8::NewLC( size );
+
+ TPtr8 aPtr = pBuffer->Des();
+ // Now the size and start Index is known, copying the data
+
+ aPtr.Copy( aBuffer.Mid( startIndex, size ) );
+
+ // Now inserting pointer
+ iPayloadizedBuffers.InsertL( pBuffer, iNalCount );
+ CleanupStack::Pop( pBuffer );
+ pBuffer = NULL; // ownership transferred
+ iNalCount++;
+ }
+
+ aNalCount = iNalCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::PayloadizeFrameNonInterleavedModeL()
+// Purpose : This function receives the encoded frame and payloadizes it
+// according to the Non-Interleaved Mode
+// Parameters : aBuffer - Buffer containing the encoded frame
+// aTimeStamp - Timestamp to go into RTP
+// aMarkerBit - Marker Bit indication (this function sets it for key frames)
+// aNalCount - This function returns the number of packetized
+// NAL units through this variable.
+// Return Value: none, leaves if an error occured
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::PayloadizeFrameNonInterleavedModeL(
+ TDes8& aBuffer,
+ TUint32 aTimeStamp,
+ TUint32& aMarkerBit,
+ TInt& aNalCount )
+ {
+ iNalCount = 0;
+ aNalCount = 0; // resetting value coming from above
+ iBufferIndex = 0;
+
+ TInt startIndex = 0;
+ TInt endIndex = 0;
+ TInt size = 0;
+ TInt count = 0; // variable to keep track of the size of aggregated packet.
+
+ aNalCount = 0;
+
+ // loop to find and packetize all NAL Units in the frame
+ while( ETrue )
+ {
+ startIndex = TMccCodecInfo::FindAvcNaluStart( iBufferIndex, aBuffer );
+ if ( startIndex == KErrNotFound )
+ {
+ break;
+ }
+
+ endIndex = TMccCodecInfo::FindAvcNaluEnd( iBufferIndex, aBuffer );
+ if ( endIndex == KErrNotFound )
+ {
+ break;
+ }
+
+ if ( startIndex == endIndex )
+ {
+ break;
+ }
+
+ // finding size of the NAL unit
+ size = endIndex - startIndex;
+
+ __ASSERT_ALWAYS( size > 0, User::Leave( KErrGeneral ) ); // some flaw in logic
+
+ // Now startIndex and size of this NAL Unit are known
+ // decide if SNALU packetization or STAP or FU-A is required
+ if ( size > iMaxPacketSize )
+ {
+ // if any NALU there for aggregation or SNALU, payloadize it first
+ if ( iToPayloadizeCount > 0 )
+ {
+ PayloadizeNaluL( aBuffer, aTimeStamp, aMarkerBit, aNalCount );
+
+ count = 0; // resetting count of bytes for aggregation packets
+ iToPayloadizeCount = 0;
+ }
+
+ FragmentNaluL( aBuffer, aTimeStamp, aMarkerBit, aNalCount, startIndex, size, 0 );
+ }
+ else if ( size <= iMaxPacketSize )
+ {
+ if( size + count > iMaxPacketSize )
+ {
+ // make STAP-A or SNALU based on number of elements in the buffer
+ PayloadizeNaluL( aBuffer, aTimeStamp, aMarkerBit, aNalCount );
+
+ count = 0; // resetting count of bytes for aggregation packets
+ iToPayloadizeCount = 0;
+ }
+ // Insert current NALU into the Buffer.
+ iToPayloadizeBuffer.InsertL( startIndex, iToPayloadizeCount );
+ iToPayloadizeSizeBuffer.InsertL( size, iToPayloadizeCount );
+ iToPayloadizeCount++;
+ count += size;
+ }
+ } // end while()
+
+ // packetizing any last NALUs left in the buffer
+ if ( iToPayloadizeCount > 0 )
+ {
+ PayloadizeNaluL( aBuffer, aTimeStamp, aMarkerBit, aNalCount );
+ count = 0;
+ iToPayloadizeCount = 0;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::PayloadizeNaluL()
+// Purpose : This function makes a SNALU packet or STAP-A packet based on the
+// number of NALUs in the array iToPayloadizeBuffer.
+// Parameters : aBuffer - Buffer containing the encoded frame
+// aTimeStamp - Timestamp to go into RTP
+// aMarkerBit - Marker Bit indication (this function sets it for key frames)
+// aNalCount - This function returns the number of packetized
+// NAL units through this variable.
+// aStartIndex - Index to the starting of the NALU
+// Return Value: none, leaves if an error occured
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::PayloadizeNaluL(
+ TDes8 & aBuffer,
+ TUint32 /*aTimeStamp*/,
+ TUint32& /*aMarkerBit*/,
+ TInt & aNalCount )
+ {
+ TInt startIndex = 0;
+ TInt size = 0;
+
+ __ASSERT_ALWAYS( iToPayloadizeCount > 0, User::Leave( KErrArgument ) );
+
+ __ASSERT_ALWAYS( iToPayloadizeBuffer.Count() == iToPayloadizeSizeBuffer.Count(),
+ User::Leave( KErrArgument ) );
+
+ if ( iToPayloadizeCount == 1 ) // SNALU packet
+ {
+ startIndex = iToPayloadizeBuffer[0];
+ size = iToPayloadizeSizeBuffer[0];
+ TPtr8 start = aBuffer.MidTPtr( startIndex );
+ AddSnaluPacketL( start, size );
+ }
+ else // payloadize STAP-A packet
+ {
+ TInt count = 0;
+ TInt totalSize = 0;
+ TUint8 headerByte = 0;
+
+ for ( count = 0; count < iToPayloadizeCount; count++ )
+ {
+ // finding total size of all the NALU's to aggregate
+ totalSize += iToPayloadizeSizeBuffer[count];
+ }
+
+ // addding the total size fields and STAP-A header size
+ totalSize += ( iToPayloadizeCount*2 + 1 );
+
+ count = 0;
+
+ // allocating memory for the total buffer size
+ HBufC8* pBuffer = HBufC8::NewLC( totalSize );
+
+ TUint16 value = 0;
+ TPtr8 pDes1 = pBuffer->Des();
+
+ headerByte = PACKET_STAP_A | ( aBuffer[iToPayloadizeBuffer[count]] & ( 0x7 << 5 ) );
+ pDes1.Append( &headerByte, 1 );
+
+ // Pps and sps are handled as SNALUs,
+ // if there's nothing else to packetize, stap-a packet is not created
+ TBool stapPacketCreated( EFalse );
+ for( count = 0; count < iToPayloadizeCount; count++ )
+ {
+ startIndex = iToPayloadizeBuffer[count];
+ size = iToPayloadizeSizeBuffer[count];
+ TPtr8 pStart = aBuffer.MidTPtr( startIndex ); // getting start index
+
+ if ( TMccCodecInfo::IsAvcPpsOrSpsData( pStart, ETrue ) )
+ {
+ AddSnaluPacketL( pStart, size );
+ }
+ else
+ {
+ // convert to network byte order
+ value = ByteOrder::Swap16( static_cast<TUint16>( size ) );
+ TUint8* ptrByte = reinterpret_cast<TUint8*>( &value );
+ pDes1.Append( ptrByte, 2 );
+ pDes1.Append( pStart.Ptr(), size );
+ stapPacketCreated = ETrue;
+ }
+ }
+
+ if ( stapPacketCreated )
+ {
+ // inserting stap-a packet into the payloadized NAL unit buffer for retrieval
+ iPayloadizedBuffers.InsertL( pBuffer, iNalCount );
+ iNalCount++;
+ CleanupStack::Pop(pBuffer);
+ }
+ else
+ {
+ // stap-a packet not created
+ CleanupStack::PopAndDestroy(pBuffer);
+ }
+ }
+
+ //Now cleaning up the buffer
+ iToPayloadizeBuffer.Reset();
+ iToPayloadizeSizeBuffer.Reset();
+ iToPayloadizeCount = 0;
+
+ aNalCount = iNalCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CRFC3984Encode::FragmentNaluL()
+// Purpose : This function receives the starting index of a NALU in a buffer and
+// fragments the NAL unit
+// Parameters : aBuffer - Buffer containing the encoded frame
+// aTimeStamp - Timestamp to go into RTP
+// aMarkerBit - Marker Bit indication (this function sets it for key frames)
+// aNalCount - This function returns the number of packetized NAL units
+// through this variable.
+// aStartIndex - Index to the starting of the NALU
+// aSize - Size of the NALU
+// aDon - valeu of Decoding order number , 16 bit value
+// Return Value: none, leaves if an error occured
+// -----------------------------------------------------------------------------
+//
+
+void CRFC3984Encode::FragmentNaluL(
+ TDes8 & aBuffer,
+ TUint32 /*aTimeStamp*/,
+ TUint32 & aMarkerBit,
+ TInt & aNalCount,
+ TInt aStartIndex,
+ TInt aSize,
+ TUint16 aDON )
+ {
+ TInt index = 0;
+ TInt fragsPacketized = 0;
+ TUint8 headerByte = 0; // FU-A packet header byte (contains F, NRI, Type Fields)
+ TUint8 fragHeaderByte = 0;
+ TInt length = 0;
+ // maximum size of fragment, 4 is to cater for DON field in FU-B
+ TInt fragMaxSize = iMaxPacketSize - 4;
+ TInt fragSize = 0; // size of fragment
+ HBufC8 * pBuffer = NULL;
+
+ // index keeps track of indexes in the buffer
+ index = aStartIndex;
+ // length of data packetized, the code decrements this after each fragment is made
+ length = aSize;
+
+ while ( length > 0 )
+ {
+ // Actually should be based on (PacketizationMode == INTERLEAVED && fragsPacketized == 0)
+ TBool fuB = EFalse;
+
+ headerByte = aBuffer[aStartIndex] & ( 0x07 << 5 ); // Extracting F and NRI bits
+
+ // taking lower 5 type bits and putting into fragHeader
+ fragHeaderByte = aBuffer[aStartIndex] & 0x1f;
+
+ if ( fragsPacketized == 0 )
+ {
+ fragHeaderByte |= (0x1 << 7); // setting start bit
+ }
+
+ if ( length <= fragMaxSize )
+ {
+ fragHeaderByte |= ( 0x1 << 6 ); // setting end byte
+ aMarkerBit = 1;
+ }
+ else
+ {
+ aMarkerBit = 0;
+ }
+
+ if ( fragsPacketized == 0 ) // skipping payload header byte for FU packets
+ {
+ index += 1;
+ length -= 1;
+ }
+
+ fragSize = ( length > fragMaxSize ) ? fragMaxSize+2 : length+2; // 2 bytes for headers
+
+ if( !fuB )
+ {
+ headerByte |= PACKET_FU_A;
+ }
+ else
+ {
+ fragSize += 2; // for additional DON field
+ headerByte |= PACKET_FU_B;
+ }
+
+ // allocating memory for fragmented NAL unit
+ pBuffer = HBufC8::NewLC(fragSize);
+
+ TPtr8 pDes = pBuffer->Des(); //new (ELeave) TBuf8<size>;
+ pDes.Append( &headerByte, 1 ); // appending FU-A packet header byte
+ pDes.Append( &fragHeaderByte, 1 ); // appending Fragment header
+
+ if ( fuB )
+ {
+ // writing DON in network byte order
+ TUint16 val = ByteOrder::Swap16( aDON );
+ TUint8* ptrByte = reinterpret_cast<TUint8*>( &val );
+ pDes.Append( ptrByte, 2 );
+ }
+
+ TPtr8 pStart = aBuffer.MidTPtr( index ); // pStart contains the data pointer
+
+ if ( !fuB )
+ {
+ pDes.Append( pStart.Ptr(), fragSize-2 ); // copying data
+ index += Min( length, fragMaxSize );
+ length -= ( fragSize-2 );
+ }
+ else
+ {
+ // copying data, subtracting DON and header size from total size to copy
+ pDes.Append( pStart.Ptr( ), fragSize-4 );
+ index += Min( length, fragMaxSize );
+ length -= ( fragSize-4 );
+ }
+
+
+ // inserting into the payloadized NAL unit buffer for retreival
+ iPayloadizedBuffers.InsertL( pBuffer, iNalCount );
+ iNalCount++;
+ CleanupStack::Pop( pBuffer );
+ pBuffer = NULL; // ownership transferred
+
+ fragsPacketized++; // to count the number of fragments
+
+ } // end while()
+
+ aNalCount = iNalCount;
+ }
+
+
+HBufC8 * CRFC3984Encode::GetNalUnitsInOrder( TInt & aIndex )
+ {
+ HBufC8 *pBuffer;
+ if ( aIndex < iNalCount )
+ {
+ pBuffer = iPayloadizedBuffers[aIndex];
+ return (pBuffer);
+ }
+ else
+ {
+ return NULL;
+ }
+
+ }
+
+void CRFC3984Encode::ClearNalBuffers()
+ {
+ TInt count = 0;
+ HBufC8 * pBuffer = NULL;
+
+ for ( count = 0; count < iPayloadizedBuffers.Count(); count++ )
+ {
+ pBuffer = iPayloadizedBuffers[count];
+ delete pBuffer;
+ pBuffer = NULL;
+ iPayloadizedBuffers[count] = NULL;
+ }
+
+ iPayloadizedBuffers.Reset();
+ iNalCount = 0;
+ }
+
+void CRFC3984Encode::AddSnaluPacketL( TPtr8 aStart, TInt aSize )
+ {
+ HBufC8* pBuffer = HBufC8::NewLC( aSize );
+
+ TPtr8 pPtr = pBuffer->Des();
+ pPtr.Copy( aStart.Ptr(), aSize );
+
+ // inserting into the payloadized NAL unit buffer for retreival
+ iPayloadizedBuffers.InsertL( pBuffer, iNalCount );
+ iNalCount++;
+ CleanupStack::Pop( pBuffer );
+ }
+
+// End of file
+