--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmcch263payloadformat/src/mcch263oldpayloadencoder.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,377 @@
+/*
+* Copyright (c) 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:
+*
+*/
+
+
+
+// ============================ INCLUDES =======================================
+
+#include "mcch263oldpayloadencoder.h"
+#include "mcch263formatlogs.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+
+// -----------------------------------------------------------------------------
+// CIPMediaVideoSink::NewL()
+// First stage constructor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CMccH263OldPayloadEncoder* CMccH263OldPayloadEncoder::NewL()
+ {
+ return new ( ELeave ) CMccH263OldPayloadEncoder();
+ }
+
+CMccH263OldPayloadEncoder::~CMccH263OldPayloadEncoder()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CIPMediaVideoSink::WriteBufferL()
+// Write media buffer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMccH263OldPayloadEncoder::EncodeL(
+ CMMFBuffer* aMMFBuffer,
+ RPointerArray<CBufferContainer>& aDesBuffers )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, enter")
+
+ CMMFDataBuffer* buf = static_cast<CMMFDataBuffer*>( aMMFBuffer );
+ iSendHeader.iMarker = 0;
+
+ // Get timestamp to RTP header. conversion to 90kHz clock
+ TInt64 tmpStamp = ( buf->TimeToPlay().Int64() + iTimeStamp.Int64() ) / KConst100 * KConst9 ;
+ iSendHeader.iTimestamp = TRtpTimeStamp( tmpStamp ) ;
+
+ __H263FORMAT_MEDIA_INT2( "CMccH263OldPayloadEncoder::EncodeL, TimeStamp:",
+ iSendHeader.iTimestamp, "Length:", buf->BufferSize() )
+
+ // Reset marker from last frame
+ iSendHeader.iMarker = 0;
+
+ // Get pointer to raw data
+ TPtrC8 frame = buf->Data();
+
+ // Check that descriptor length is included.
+ // Missing length causes panic in frame.Mid() function
+ if ( frame.Length() == 0 || buf->BufferSize() != frame.Length() )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, ERROR Buffer corrupted")
+ User::Leave( KErrBadDescriptor );
+ }
+
+ const TUint8 *dataPtr = buf->Data().Ptr();
+ // Get buffer length
+ TUint frameLength = buf->BufferSize();
+
+ // Get frame header information
+ GetHeaderInfoL( frame );
+
+ // If packet is smaller than max Packet size. Send right away
+ if ( frame.Length() <= TInt( KVideoPacketSize ) )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, Sending whole frame...")
+
+ // Set marker to indicate last packet of current frame
+ CreateNewBufferL( aMMFBuffer,
+ aDesBuffers,
+ frame,
+ frameLength + KConst4,
+ 1 );
+
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, exit" )
+ return;
+ }
+
+ // Initialize splitting variables
+ TInt lastGOB = 0;
+ TInt lastsend = 0;
+
+ // Scan frame for GOBs
+ for( TUint i= 0; i < frameLength; i++ )
+ {
+ dataPtr += i;
+ if ( *dataPtr == TUint8( 0x00 ) )
+ {
+ dataPtr++;
+ if ( *dataPtr == TUint8( 0x00 ) )
+ {
+ dataPtr++;
+ if ( TUint8( *dataPtr&0xfc )>0x80 )
+ {
+ if ( ( i - lastsend ) >= KVideoPacketSize && lastGOB )
+ {
+ __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(scan gobs), Sending packet f",
+ lastsend, "len", ( lastGOB - lastsend ) )
+
+ // Packet size exceeded send new RTP Packet
+ TPtrC8 packetData =
+ frame.Mid( lastsend, ( lastGOB - lastsend ) );
+
+ CreateNewBufferL( aMMFBuffer,
+ aDesBuffers,
+ packetData,
+ packetData.Length() + KConst4,
+ iSendHeader.iMarker );
+
+ lastsend = lastGOB;
+ }
+ lastGOB = i;
+ }
+ }
+ }
+ // Return pointer to begining of frame
+ dataPtr = frame.Ptr();
+ }
+
+ // Check that last packet does not exceed packet size
+ if ( ( frameLength - lastsend ) >= KVideoPacketSize && lastsend != 0 )
+ {
+ __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(last packet check), Sending packet f",
+ lastsend, "len", ( lastGOB - lastsend ) )
+
+ TPtrC8 packetData =
+ frame.Mid( lastsend, ( lastGOB - lastsend ) );
+
+ CreateNewBufferL( aMMFBuffer,
+ aDesBuffers,
+ packetData,
+ packetData.Length() + KConst4,
+ iSendHeader.iMarker );
+
+ lastsend = lastGOB;
+ }
+
+ // Send last packet to RTP API
+ if ( lastsend != 0 )
+ {
+ __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(last packet), Sending packet f",
+ lastsend, "len", ( frameLength - lastsend ) )
+
+ TPtrC8 packetData =
+ frame.Mid( lastsend, ( frameLength - lastsend ) );
+
+ // Set marker to indicate last packet of current frame
+ CreateNewBufferL( aMMFBuffer,
+ aDesBuffers,
+ packetData,
+ packetData.Length() + KConst4,
+ 1 );
+
+ }
+
+ // Special case no GOBs found try to send whole frame
+ else
+ {
+ __H263FORMAT_MEDIA_INT1("CMccH263OldPayloadEncoder::EncodeL(no gobs), Sending whole packet len",
+ frameLength )
+
+ if ( buf->BufferSize() > TInt( KVideoPacketSize + KConst4 ) )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, ERROR, too big frame, exit")
+
+ return;
+ }
+
+ // Set marker to indicate last packet of current frame
+ CreateNewBufferL( aMMFBuffer,
+ aDesBuffers,
+ frame,
+ frameLength + KConst4,
+ 1 );
+
+ }
+
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, exit")
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMccH263OldPayloadEncoder::WriteHeaderData()
+// Write payload header information byte
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CMccH263OldPayloadEncoder::WriteHeaderData( TInt aByte )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::WriteHeaderData")
+
+ //byte to be written
+ TUint8 wbyte = 0;
+ //construct needed byte
+ switch ( aByte )
+ {
+ case 0:
+ {
+ wbyte |= TUint8( headerA.F << KConst7 );
+ wbyte |= TUint8( headerA.P << KConst6 );
+ wbyte |= TUint8( headerA.SBIT << KConst3 );
+ wbyte |= TUint8( headerA.EBIT );
+ }break;
+ case 1:
+ {
+ wbyte |= TUint8( headerA.SRC << KConst5 );
+ wbyte |= TUint8( headerA.I << KConst4 );
+ wbyte |= TUint8( headerA.U << KConst3 );
+ wbyte |= TUint8( headerA.S << KConst2 );
+ wbyte |= TUint8( headerA.A << 1 );
+ }break;
+ case KConst2:
+ {
+ wbyte |= TUint8( headerA.DBQ << KConst3 );
+ wbyte |= TUint8( headerA.TRB );
+ }break;
+ case KConst3:
+ {
+ wbyte = headerA.TR;
+ }break;
+ default:
+ {
+ }break;
+ }
+ //return constructed byte
+ return wbyte;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccH263OldPayloadEncoder::GetHeaderInfoL()
+// Get video frame header information
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMccH263OldPayloadEncoder::GetHeaderInfoL( TDesC8& aFrame )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::GetHeaderInfoL")
+
+ //fill in default values = 0
+ headerA.F = 0;
+ headerA.P = 0;
+ headerA.SBIT = 0;
+ headerA.EBIT = 0;
+ headerA.SRC = 0;
+ headerA.I = 0;
+ headerA.U = 0;
+ headerA.S = 0;
+ headerA.A = 0;
+ headerA.R = 0;
+ headerA.DBQ = 0;
+ headerA.TRB = 0;
+ headerA.TR = 0;
+
+ //A S S U M I N G that aFrame begins with PSC
+ const TUint8 *help;
+ help = aFrame.Ptr();
+ //goto PTYPE-field
+ help += KConst4;
+ TUint8 test = 0;
+ //get SRC
+ test = TUint8( *help & 0x1c );
+ test >>= KConst2;
+ headerA.SRC = test;
+ if( headerA.SRC == KConst7 )
+ {
+ #ifdef LOG
+ IPUL_LOGC( 1, "VSink::GetHeaderInfoL> ERROR: Picture format unsupported" );
+ #endif
+ }
+ //get I parameter
+ test = 0;
+ test = TUint8( *help & 0x02 );
+ test >>= 1;
+ headerA.I = test;
+ //get U parameter
+ test = 0;
+ test = TUint8( *help & 0x01 );
+ headerA.U = test;
+ //get S parameter
+ help++;
+ test = 0;
+ test = TUint8( *help & 0x80 );
+ test >>= KConst7;
+ headerA.S = test;
+ //get A parameter
+ test = 0;
+ test = TUint8( *help & 0x40 );
+ test >>= KConst6;
+ headerA.A = test;
+ //get P parameter
+ test = 0;
+ test = TUint8( *help & 0x20 );
+ test >>= KConst5;
+ headerA.P = test;
+ //check for correct file format
+ if ( headerA.P != 0 )
+ {
+ #ifdef LOG
+ IPUL_LOGC( 1 , "VSink::GetHeaderInfoL> ERROR: Unsupported file format" );
+ #endif
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMccH263OldPayloadEncoder::SetPayloadType()
+// -----------------------------------------------------------------------------
+//
+void CMccH263OldPayloadEncoder::SetPayloadType( TUint8 aPayloadType )
+ {
+ __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::SetPayloadType")
+
+ iSendHeader.iPayloadType = aPayloadType;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccH263OldPayloadEncoder::CreateNewBufferL()
+// -----------------------------------------------------------------------------
+//
+void CMccH263OldPayloadEncoder::CreateNewBufferL(
+ CMMFBuffer* aMMFBuffer,
+ RPointerArray<CBufferContainer>& aDesBuffers,
+ const TDesC8& aPacketData,
+ TInt aLength,
+ TInt aMarker )
+ {
+ CMMFDataBuffer* newBuffer =
+ CMMFDataBuffer::NewL( aLength );
+ CleanupStack::PushL( newBuffer );
+ newBuffer->Data().Append( WriteHeaderData( 0 ) );
+ newBuffer->Data().Append( WriteHeaderData( 1 ) );
+ newBuffer->Data().Append( WriteHeaderData( KConst2 ) );
+ newBuffer->Data().Append( WriteHeaderData( KConst3 ) );
+ newBuffer->Data().Append( aPacketData );
+ newBuffer->SetTimeToPlay( aMMFBuffer->TimeToPlay() );
+ newBuffer->SetFrameNumber( aMMFBuffer->FrameNumber() + iSequenceNumIncrementer );
+
+ // If frame is divided in several packets, sequence numbers of following
+ // packets have to be modified
+ if ( aMarker == 0 )
+ {
+ iSequenceNumIncrementer++;
+ }
+
+ CBufferContainer* cont = new (ELeave) CBufferContainer();
+ CleanupStack::Pop( newBuffer );
+ cont->iBuffer = newBuffer;
+ iSendHeader.iMarker = aMarker;
+ cont->iSendHeader = iSendHeader;
+ CleanupStack::PushL( cont );
+ aDesBuffers.AppendL( cont );
+ CleanupStack::Pop( cont );
+ }
+