diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmcch263payloadformat/src/mcch263oldpayloadencoder.cpp --- /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& aDesBuffers ) + { + __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, enter") + + CMMFDataBuffer* buf = static_cast( 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& 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 ); + } +