--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/avcedit/src/vedavceditimp.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,1005 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "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:
+* Ixonos Plc
+*
+* Description:
+* Implementation class for AVC editing operations.
+*
+*/
+
+
+#include <e32svr.h>
+#include <mmf/devVideo/avc.h>
+
+#include "biblin.h"
+#include "bitbuffer.h"
+#include "vld.h"
+#include "vedavceditimp.h"
+
+// Debug print macro
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x;
+#else
+#define PRINT(x)
+#endif
+
+// An assertion macro wrapper to clean up the code a bit
+#define VPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CVedAVCEdit"), -10000))
+
+// ================= MEMBER FUNCTIONS =======================
+
+// Two-phased constructor
+CVedAVCEditImp* CVedAVCEditImp::NewL()
+{
+ CVedAVCEditImp* self = new (ELeave) CVedAVCEditImp();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+}
+
+// C++ default constructor
+CVedAVCEditImp::CVedAVCEditImp()
+ {
+ }
+
+// Symbian OS default constructor can leave
+void CVedAVCEditImp::ConstructL()
+ {
+
+ iAvcDecoder = avcdOpen();
+
+ if (!iAvcDecoder)
+ {
+ User::Leave(KErrNoMemory);
+ }
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+ iNalLengthSize = 4;
+ iOutputLevel = 10;
+#endif
+
+ }
+
+// Destructor
+CVedAVCEditImp::~CVedAVCEditImp()
+ {
+ avcdClose(iAvcDecoder);
+ }
+
+
+// ---------------------------------------------------------7
+// AVCEditParser::ProcessAVCBitStream
+// Process one input AVC frame, i.e., convert to MDF NAL unit
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::ProcessAVCBitStreamL(TDes8& aBuf, TInt& aFrameLen, TInt aDecInfoSize, TBool aFirstFrame)
+ {
+
+ TUint8* dataBuffer = (TUint8*)(aBuf.Ptr());
+
+ // Calculate NAL header start offset
+ TInt offset = (((aFrameLen - 1) / 4) + 1) * 4; // Align at 32-bit boundrary
+ TInt numNALUnits = 0;
+
+ if (aFirstFrame) // There are several NAL units: decoder info and the frame
+ {
+ // how many bytes used for length
+ iFrameLengthBytes = ( dataBuffer[4] & 0x3 ) + 1;
+
+ // Index where to read configuration data
+ TInt index = 5; // Skip version and length information
+
+ TInt numOfSPS = dataBuffer[index] & 0x1f;
+ index++;
+
+ // Loop all SPS units
+ for (TInt i = 0; i < numOfSPS; ++i)
+ {
+ TInt SPSSize = (dataBuffer[index] << 8) + dataBuffer[index + 1];
+ index += 2;
+
+ // Set NAL start offset
+ dataBuffer[offset + 0] = TUint8(index & 0xff);
+ dataBuffer[offset + 1] = TUint8((index >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((index >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((index >> 24) & 0xff);
+
+ // Set NAL size
+ dataBuffer[offset + 4] = TUint8(SPSSize & 0xff);
+ dataBuffer[offset + 5] = TUint8((SPSSize >> 8) & 0xff);
+ dataBuffer[offset + 6] = TUint8((SPSSize >> 16) & 0xff);
+ dataBuffer[offset + 7] = TUint8((SPSSize >> 24) & 0xff);
+
+ offset += 8;
+ index += SPSSize;
+ numNALUnits++;
+ }
+
+ TInt numOfPPS = dataBuffer[index];
+ index++;
+
+ // Loop all PPS units
+ for (TInt i = 0; i < numOfPPS; ++i)
+ {
+ TInt PPSSize = (dataBuffer[index] << 8) + dataBuffer[index + 1];
+ index += 2;
+
+ // Set NAL start offset
+ dataBuffer[offset + 0] = TUint8(index & 0xff);
+ dataBuffer[offset + 1] = TUint8((index >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((index >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((index >> 24) & 0xff);
+
+ // Set NAL size
+ dataBuffer[offset + 4] = TUint8(PPSSize & 0xff);
+ dataBuffer[offset + 5] = TUint8((PPSSize >> 8) & 0xff);
+ dataBuffer[offset + 6] = TUint8((PPSSize >> 16) & 0xff);
+ dataBuffer[offset + 7] = TUint8((PPSSize >> 24) & 0xff);
+
+ offset += 8;
+ index += PPSSize;
+ numNALUnits++;
+ }
+
+ TInt totalFrameSize = aFrameLen;
+ TInt currentProcessed = aDecInfoSize + 4; // skip DCR & length
+ TUint8* frameLenPtr = const_cast<TUint8*>(aBuf.Ptr()) + aDecInfoSize;
+
+ TInt frameSize = 0;
+
+ // loop all slice NAL units
+ while (currentProcessed < totalFrameSize)
+ {
+
+ // Set the NAL start offset
+ dataBuffer[offset + 0] = TUint8(currentProcessed & 0xff);
+ dataBuffer[offset + 1] = TUint8((currentProcessed >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((currentProcessed >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((currentProcessed >> 24) & 0xff);
+
+ frameSize = (frameLenPtr[0] << 24) + (frameLenPtr[1] << 16) +
+ (frameLenPtr[2] << 8) + frameLenPtr[3];
+
+ // Set the NAL size
+ dataBuffer[offset + 4] = TUint8(frameSize & 0xff);
+ dataBuffer[offset + 5] = TUint8((frameSize >> 8) & 0xff);
+ dataBuffer[offset + 6] = TUint8((frameSize >> 16) & 0xff);
+ dataBuffer[offset + 7] = TUint8((frameSize >> 24) & 0xff);
+
+ frameLenPtr += (4 + frameSize);
+ currentProcessed += (4 + frameSize);
+ offset += 8;
+ numNALUnits++;
+
+ }
+
+ // Set Number of NAL units
+ dataBuffer[offset + 0] = TUint8(numNALUnits & 0xff);
+ dataBuffer[offset + 1] = TUint8((numNALUnits >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((numNALUnits >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((numNALUnits >> 24) & 0xff);
+
+ aFrameLen = offset + 4;
+ }
+ else
+ { // process just the frame
+
+ TInt totalFrameSize = aFrameLen;
+ TInt currentProcessed = 4; // skip length
+ TUint8* frameLenPtr = const_cast<TUint8*>(aBuf.Ptr());
+
+ TInt frameSize = 0;
+
+ // loop all slice NAL units
+ while (currentProcessed < totalFrameSize)
+ {
+ // Set the NAL start offset
+ dataBuffer[offset + 0] = TUint8(currentProcessed & 0xff);
+ dataBuffer[offset + 1] = TUint8((currentProcessed >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((currentProcessed >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((currentProcessed >> 24) & 0xff);
+
+ frameSize = (frameLenPtr[0] << 24) + (frameLenPtr[1] << 16) +
+ (frameLenPtr[2] << 8) + frameLenPtr[3];
+
+ // Set the NAL size
+ dataBuffer[offset + 4] = TUint8(frameSize & 0xff);
+ dataBuffer[offset + 5] = TUint8((frameSize >> 8) & 0xff);
+ dataBuffer[offset + 6] = TUint8((frameSize >> 16) & 0xff);
+ dataBuffer[offset + 7] = TUint8((frameSize >> 24) & 0xff);
+
+ frameLenPtr += (4 + frameSize);
+ currentProcessed += (4 + frameSize);
+ offset += 8;
+ numNALUnits++;
+ }
+
+ // Number of NAL units
+ dataBuffer[offset + 0] = TUint8(numNALUnits & 0xff);
+ dataBuffer[offset + 1] = TUint8((numNALUnits >> 8) & 0xff);
+ dataBuffer[offset + 2] = TUint8((numNALUnits >> 16) & 0xff);
+ dataBuffer[offset + 3] = TUint8((numNALUnits >> 24) & 0xff);
+
+ aFrameLen = offset + 4;
+ }
+ //iDataLength = iCurrentFrameLength;
+ }
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::GetMaxAVCFrameBuffering
+// Calculate maximum amount of buffered AVC frames
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::GetMaxAVCFrameBuffering(TInt aLevel, TSize aResolution)
+ {
+
+ TReal maxDPB = 0.0;
+ switch (aLevel)
+ {
+ case 11:
+ maxDPB = 337.5;
+ break;
+
+ case 12:
+ maxDPB = 891.0;
+ break;
+
+ case 10:
+ case 101:
+ default:
+ maxDPB = 148.5;
+ break;
+ }
+
+ TInt mbWidth = aResolution.iWidth / 16;
+ TInt mbHeight = aResolution.iHeight / 16;
+
+ TInt maxDPBSize = TInt( ( TReal(1024.0) * maxDPB ) / ( TReal(mbWidth*mbHeight*384.0) ) );
+
+ maxDPBSize = min(maxDPBSize, 16);
+
+ return maxDPBSize;
+ }
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::GetLevel
+// Get input bitstream level from SPS
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::GetLevel(TDesC8& aBuf, TInt& aLevel)
+ {
+ TUint8* buffer = (TUint8*)(aBuf.Ptr());
+
+ TInt index = 5; // Skip version and length information
+
+#ifdef _DEBUG
+ TInt numOfSPS = buffer[index] & 0x1f;
+ VPASSERT(numOfSPS == 1);
+#endif
+
+ index++;
+
+ TUint SPSSize = (buffer[index] << 8) + buffer[index + 1];
+ index += 2;
+
+ TInt error = avcdParseLevel(iAvcDecoder, (void*)&buffer[index], &SPSSize, aLevel);
+
+ if (error != KErrNone)
+ return error;
+
+ return KErrNone;
+ }
+
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::GetResolution
+// Get input bitstream resolution from SPS
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::GetResolution(TDesC8& aBuf, TSize& aResolution)
+{
+
+ TUint8* buffer = (TUint8*)(aBuf.Ptr());
+
+ TInt index = 5; // Skip version and length information
+
+#ifdef _DEBUG
+ TInt numOfSPS = buffer[index] & 0x1f;
+ VPASSERT(numOfSPS == 1);
+#endif
+
+ index++;
+
+ TUint SPSSize = (buffer[index] << 8) + buffer[index + 1];
+ index += 2;
+
+ TInt error = avcdParseResolution(iAvcDecoder, (void*)&buffer[index], &SPSSize,
+ aResolution.iWidth, aResolution.iHeight);
+
+ if (error != KErrNone)
+ return error;
+
+ return KErrNone;
+}
+
+
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+// ---------------------------------------------------------
+// AVCEditParser::SaveAVCDecoderConfigurationRecordL
+// Saves SPS/PPS Nal units from AVCDecoderConfigurationRecord
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::SaveAVCDecoderConfigurationRecordL(TDes8& aBuf, TBool aFromEncoder)
+ {
+
+ TUint8* buffer = (TUint8*)(aBuf.Ptr());
+
+ TInt index = 5; // Skip version and length information
+
+ TInt numOfSPS = buffer[index] & 0x1f;
+ index++;
+
+ // Loop all SPS units
+ for (TInt i = 0; i < numOfSPS; ++i)
+ {
+ TUint SPSSize = (buffer[index] << 8) + buffer[index + 1];
+ index += 2;
+
+ // feed NAL for saving to ParseParameterSet()
+ User::LeaveIfError( ParseParameterSet( (void*)&buffer[index], &SPSSize, aFromEncoder ) );
+ index += SPSSize;
+
+ }
+
+ TInt numOfPPS = buffer[index];
+ index++;
+
+ // Loop all PPS units
+ for (TInt i = 0; i < numOfPPS; ++i)
+ {
+ TUint PPSSize = (buffer[index] << 8) + buffer[index + 1];
+ index += 2;
+
+ // feed NAL for saving to ParseParameterSet()
+ User::LeaveIfError( ParseParameterSet( (void*)&buffer[index], &PPSSize, aFromEncoder ) );
+ index += PPSSize;
+
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::ConvertAVCHeader
+// Convert AVC specific decoder config info to
+// AVCDecoderConfigurationRecord -format
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::ConvertAVCHeaderL( TDesC8& aSrcBuf, TDes8& aDstBuf )
+ {
+
+ TUint8* inputPtr = (TUint8*)(aSrcBuf.Ptr());
+ TUint8* outputPtr = (TUint8*)(aDstBuf.Ptr());
+ TUint8* spsPtr;
+ TUint8* ppsPtr;
+
+ TUint numSPS = 0;
+ TUint numPPS = 0;
+
+ TUint totalSPSLength = 0;
+ TUint totalPPSLength = 0;
+
+ TUint headerLength = aSrcBuf.Length();
+ TUint endIndex = headerLength;
+
+ TInt nalType = 0;
+ TUint nalLength;
+ TUint nalIndex;
+ TUint nalOffset;
+
+ // Allocate memory for the temporary buffers
+ HBufC8* temp1 = (HBufC8*) HBufC8::NewLC(1000);
+ HBufC8* temp2 = (HBufC8*) HBufC8::NewLC(5000);
+
+ spsPtr = const_cast<TUint8*>( temp1->Des().Ptr() );
+ ppsPtr = const_cast<TUint8*>( temp2->Des().Ptr() );
+
+ TUint numNalUnits = inputPtr[endIndex-4] + (inputPtr[endIndex-3]<<8) + (inputPtr[endIndex-2]<<16) + (inputPtr[endIndex-1]<<24);
+
+ // Move endIndex to point to the first NAL unit's offset information
+ endIndex = headerLength - numNalUnits*8 - 4;
+
+ nalIndex = 0;
+
+ TUint8* copyPtr = inputPtr;
+
+ while (nalIndex < numNalUnits)
+ {
+ nalIndex++;
+
+ TInt tmp1 = inputPtr[endIndex++];
+ TInt tmp2 = inputPtr[endIndex++]<<8;
+ TInt tmp3 = inputPtr[endIndex++]<<16;
+ TInt tmp4 = inputPtr[endIndex++]<<24;
+
+ nalOffset = tmp1 + tmp2 + tmp3 + tmp4;
+
+ tmp1 = inputPtr[endIndex++];
+ tmp2 = inputPtr[endIndex++]<<8;
+ tmp3 = inputPtr[endIndex++]<<16;
+ tmp4 = inputPtr[endIndex++]<<24;
+
+ nalLength = tmp1 + tmp2 + tmp3 + tmp4;
+
+ nalType = inputPtr[nalOffset] & 0x1F;
+
+ if(nalType == 7)
+ {
+ numSPS++;
+
+ // First store the SPS unit length with two bytes
+ spsPtr[totalSPSLength] = (nalLength >> 8) & 0xFF;
+ spsPtr[totalSPSLength+1] = nalLength & 0xFF;
+
+ // Copy the SPS unit to the buffer
+ Mem::Copy(&spsPtr[totalSPSLength+2], copyPtr , nalLength);
+
+ totalSPSLength += nalLength + 2; // Two more for the size
+ }
+ else if(nalType == 8)
+ {
+ numPPS++;
+
+ // First store the SPS unit length with two bytes
+ ppsPtr[totalPPSLength] = (nalLength >> 8) & 0xFF;
+ ppsPtr[totalPPSLength+1] = nalLength & 0xFF;
+
+ // Copy the SPS unit to the buffer
+ Mem::Copy(&ppsPtr[totalPPSLength+2], copyPtr , nalLength);
+
+ totalPPSLength += nalLength + 2; // Two more for the size
+ }
+ else
+ {
+ // [KW]: Check later if this is an error!!!
+ }
+
+ copyPtr += nalLength;
+ }
+
+ // When the header has been parsed, form the AVCDecoderConfigurationRecord
+ outputPtr[0] = 0x01; // configurationVersion
+ outputPtr[1] = 0x42; // Profile indicator
+ // Profile compatibility, i.e. all 4 constrain set flags + reserved 4 zero bits
+ outputPtr[2] = 0x80; // Bitstream obeys all baseline constraints
+ if ( iOutputLevel == 101 )
+ {
+ // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
+ outputPtr[2] |= 0x10;
+ }
+ else
+ {
+ outputPtr[2] &= 0xEF;
+ }
+
+ outputPtr[3] = (iOutputLevel == 101) ? 11 : iOutputLevel; // level
+
+ outputPtr[4] = 0x03; // lengthSizeMinusOne
+ outputPtr[4] |= 0x0FC; // 6 reserved bits (all 1)
+
+ outputPtr[5] = numSPS;
+ outputPtr[5] |= 0xE0; // 3 reserved bits (all 1)
+
+ TInt len = 6;
+
+ // Copy the SPS unit(s) to the buffer
+ Mem::Copy(&outputPtr[6], spsPtr , totalSPSLength);
+
+ len += totalSPSLength;
+
+ outputPtr[6+totalSPSLength] = numPPS;
+
+ len += 1;
+
+ // Copy the PPS unit(s) to the buffer
+ Mem::Copy(&outputPtr[6+totalSPSLength+1], ppsPtr , totalPPSLength);
+
+ len += totalPPSLength;
+
+ aDstBuf.SetLength(len);
+
+ CleanupStack::Pop(2);
+
+ // Free the temporary buffers
+ delete temp1;
+ delete temp2;
+}
+
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::ParseOneNAL
+// Saves one SPS/PPS NAL unit for later use
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::ParseParameterSet(void *aNalUnitData, TUint* aNalUnitLength, TBool aFromEncoder)
+ {
+ TInt retCode;
+
+ // Pass the information about the frame origin to the decoder
+ FrameIsFromEncoder(iAvcDecoder, aFromEncoder);
+ // Just call the decoder's parser function
+ retCode = avcdParseParameterSet(iAvcDecoder, aNalUnitData, aNalUnitLength);
+
+ return retCode;
+ }
+
+TInt CVedAVCEditImp::ParseOneNAL(void *aNalUnitData, TUint* aNalUnitLength, TBool aFromEncoder)
+ {
+ TInt retCode;
+
+ // Pass the information about the frame origin to the decoder
+ FrameIsFromEncoder(iAvcDecoder, aFromEncoder);
+ // Just call the decoder's parser function
+ retCode = avcdParseOneNal(iAvcDecoder, aNalUnitData, aNalUnitLength);
+
+ return retCode;
+ }
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::ParseFrame
+// Update slice header information
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::ParseFrame(HBufC8*& aBuf, TBool aContainsDCR, TBool aFromEncoder)
+{
+ TUint nalSize;
+ TUint nalOrigSize = 0;
+ TUint nalLengthSize = 0;
+// TInt nalType;
+// TInt nalRefIdc;
+ TInt skip = 0;
+ TUint bufferLength = aBuf->Length();
+ TPtr8 bufferPtr(aBuf->Des());
+ TUint8* srcPtr = (TUint8*)(bufferPtr.Ptr());
+
+ TInt error;
+ HBufC8* temp1 = 0;
+ TRAP( error, temp1 = (HBufC8*) HBufC8::NewL(10) );
+
+ if (error != KErrNone)
+ return error;
+
+ TPtr8 tempPtr(temp1->Des());
+// TUint tmpLength1;
+// TUint tmpLength2;
+ TUint8* tempData1;
+
+ tempPtr.Append(5);
+
+ // Jump over the AVC decoder information if it's included
+ if(aContainsDCR)
+ {
+ // skip 4 bytes for
+ // configVersion, profile, profile compatibility and Level
+ skip += 4;
+
+ // skip 1 byte for lengthSizeMinusOne
+ skip += 1;
+
+ // skip 1 byte for number of sequence parameter sets
+ TInt numOfSSP = 0x1F & srcPtr[skip];
+ skip += 1;
+
+ for (TInt i = 0; i < numOfSSP; i++)
+ {
+ TInt sspSize = srcPtr[skip]*256 + srcPtr[skip+1];
+ skip += 2;
+ skip += sspSize;
+ }
+
+ TInt numOfPSP = srcPtr[skip];
+ skip += 1;
+
+ for (TInt i = 0; i < numOfPSP; i++)
+ {
+ TInt pspSize = srcPtr[skip]*256 + srcPtr[skip+1];
+ skip += 2;
+ skip += pspSize;
+ }
+ }
+
+ while (skip < bufferLength)
+ {
+
+ TInt retVal = 0;
+
+ nalLengthSize = iNalLengthSize;
+ switch (nalLengthSize)
+ {
+ case 1:
+ nalOrigSize = nalSize = srcPtr[skip];
+ skip += 1;
+ break;
+ case 2:
+ nalOrigSize = nalSize = (srcPtr[skip] << 8) + srcPtr[skip+1];
+ skip += 2;
+ break;
+ case 4:
+ nalOrigSize = nalSize = (srcPtr[skip] << 24) + (srcPtr[skip+1] << 16) +
+ (srcPtr[skip+2] << 8) + srcPtr[skip+3];
+
+ skip += 4;
+ break;
+ }
+
+// nalType = srcPtr[skip] & 0x1F;
+// nalRefIdc = srcPtr[skip] & 0x60;
+
+ // [KW]: Alloc memory here instead of sequence.cpp
+ tempData1 = (TUint8*) User::Alloc(nalOrigSize+100);
+
+ if (tempData1 == 0)
+ {
+ User::Free(temp1);
+ return KErrNoMemory;
+ }
+
+ Mem::Copy(tempData1, &srcPtr[skip], nalOrigSize*sizeof(TUint8));
+
+ Mem::FillZ(&tempData1[nalOrigSize], 100*sizeof(TUint8));
+
+ // Call ParseOneNaL function
+ retVal = ParseOneNAL(tempData1, &nalSize, aFromEncoder);
+
+ if (retVal != KErrNone)
+ {
+ User::Free(tempData1);
+ User::Free(temp1);
+ return retVal;
+ }
+
+ // Copy data back to the srcPtr
+ Mem::Copy(&srcPtr[skip],tempData1,nalOrigSize*sizeof(TUint8));
+
+// tmpLength1 = aBuf->Length();
+ if(nalSize > nalOrigSize)
+ {
+ TUint diff = nalSize - nalOrigSize;
+
+ for (TInt i=0; i<diff; i++)
+ {
+ tempPtr.Delete(0,1);
+ tempPtr.Append(tempData1[nalOrigSize+i]);
+// tmpLength2 = tempPtr.Length();
+
+ // Insert byte(s) into the buffer
+ if((bufferPtr.Length() + 1) > bufferPtr.MaxLength())
+ {
+ // extend buffer size
+ TUint newSize = bufferPtr.Length() + 1;
+
+ // round up to the next full kilobyte
+ newSize = (newSize + 1023) & (~1023);
+ TRAP(error, (aBuf = aBuf->ReAllocL(newSize)) );
+
+ if (error != KErrNone)
+ {
+ User::Free(tempData1);
+ User::Free(temp1);
+ return error;
+ }
+
+ bufferPtr.Set(aBuf->Des());
+ }
+
+ bufferPtr.Insert(skip+nalOrigSize+i,tempPtr);
+// tmpLength1 = aBuf->Length();
+ }
+ bufferLength += diff;
+ }
+ else if(nalSize < nalOrigSize)
+ {
+ TUint diff = nalOrigSize - nalSize;
+
+ // Delete diff bytes from the buffer
+ bufferPtr.Delete(skip+nalOrigSize-diff,diff);
+
+ bufferLength -= diff;
+ }
+
+ // Update the NAL unit's size information in the buffer
+ srcPtr[skip-4] = TUint8((nalSize >> 24) & 0xff);
+ srcPtr[skip-3] = TUint8((nalSize >> 16) & 0xff);
+ srcPtr[skip-2] = TUint8((nalSize >> 8) & 0xff);
+ srcPtr[skip-1] = TUint8(nalSize & 0xff);
+
+ // Free the temporary data
+ User::Free(tempData1);
+
+ skip += nalSize;
+ }
+
+ User::Free(temp1);
+
+ return KErrNone;
+}
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::ConstructAVCDecoderConfigurationRecordL
+// Constructs AVCDecoderConfigurationRecord for output
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::ConstructAVCDecoderConfigurationRecordL( TDes8& aDstBuf )
+ {
+
+ TUint8* outputPtr = (TUint8*)(aDstBuf.Ptr());
+ TUint8* spsPtr;
+ TUint8* ppsPtr;
+
+ TUint numSPS = 0;
+ TUint numPPS = 0;
+
+ TUint totalSPSLength = 0;
+ TUint totalPPSLength = 0;
+
+ TInt i;
+ TUint spsLength;
+ TUint ppsLength;
+ TInt len = 6;
+ TUint8* copyPtr;
+
+
+ // Allocate memory for the temporary buffers
+ HBufC8* temp1 = (HBufC8*) HBufC8::NewLC(1000);
+ HBufC8* temp2 = (HBufC8*) HBufC8::NewLC(5000);
+
+ spsPtr = const_cast<TUint8*>( temp1->Des().Ptr() );
+ ppsPtr = const_cast<TUint8*>( temp2->Des().Ptr() );
+
+ numSPS = ReturnNumSPS(iAvcDecoder);
+ numPPS = ReturnNumPPS(iAvcDecoder);
+
+ for (i=0; i<numSPS; i++)
+ {
+ copyPtr = ReturnSPSSet(iAvcDecoder,i,&spsLength);
+
+ // First store the SPS unit length with two bytes
+ spsPtr[totalSPSLength] = (spsLength >> 8) & 0xFF;
+ spsPtr[totalSPSLength+1] = spsLength & 0xFF;
+
+ // Copy the SPS unit to the buffer
+ Mem::Copy(&spsPtr[totalSPSLength+2], copyPtr , spsLength);
+
+ totalSPSLength += spsLength + 2; // Two more for the size
+ }
+
+
+ for (i=0; i<numPPS; i++)
+ {
+ copyPtr = ReturnPPSSet(iAvcDecoder,i,&ppsLength);
+
+ // First store the PPS unit length with two bytes
+ ppsPtr[totalPPSLength] = (ppsLength >> 8) & 0xFF;
+ ppsPtr[totalPPSLength+1] = ppsLength & 0xFF;
+
+ // Copy the PPS unit to the buffer
+ Mem::Copy(&ppsPtr[totalPPSLength+2], copyPtr , ppsLength);
+
+ totalPPSLength += ppsLength + 2; // Two more for the size
+ }
+
+
+
+ // When the header has been parsed, form the AVCDecoderConfigurationRecord
+ outputPtr[0] = 0x01;
+ outputPtr[1] = 0x42; // Profile indicator, baseline profile
+
+ // Profile compatibility, i.e. all 4 constrain set flags + reserved 4 zero bits
+ outputPtr[2] = 0x80; // Bitstream obeys all baseline constraints
+ if ( iOutputLevel == 101 )
+ {
+ // For level 1b, the 4th bit shall be == 1, otherwise it must be zero
+ outputPtr[2] |= 0x10;
+ }
+ else
+ {
+ outputPtr[2] &= 0xEF;
+ }
+
+ outputPtr[3] = (iOutputLevel == 101) ? 11 : iOutputLevel; // level
+ outputPtr[4] = 0x03; // lengthSizeMinusOne
+ outputPtr[5] = numSPS;
+
+
+ // Copy the SPS unit(s) to the buffer
+ Mem::Copy(&outputPtr[6], spsPtr , totalSPSLength);
+
+ len += totalSPSLength;
+
+ outputPtr[6+totalSPSLength] = numPPS;
+
+ len += 1;
+
+ // Copy the PPS unit(s) to the buffer
+ Mem::Copy(&outputPtr[6+totalSPSLength+1], ppsPtr , totalPPSLength);
+
+ len += totalPPSLength;
+
+ aDstBuf.SetLength(len);
+
+ CleanupStack::Pop(2);
+ // Free the temporary buffers
+ delete temp1;
+ delete temp2;
+ }
+
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::EncodeUntilIDR
+// Returns whether frames have to be encoded until next IDR frame
+// ---------------------------------------------------------
+//
+TBool CVedAVCEditImp::EncodeUntilIDR()
+{
+ if (iAvcDecoder)
+ {
+ return (ReturnEncodeUntilIDR(iAvcDecoder));
+ }
+ else
+ {
+ return EFalse;
+ }
+}
+
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::IsNALUnitIDR
+// Returns whether passed frame is an IDR frame
+// ---------------------------------------------------------
+//
+TBool CVedAVCEditImp::IsNALUnitIDR( TDes8& aNalBuf )
+{
+ TUint8* bufferPtr = (TUint8*)(aNalBuf.Ptr());
+
+ // skip 4 bytes of length information
+ if((bufferPtr[4] & 0x1F) == 5)
+ return ETrue;
+ else
+ return EFalse;
+}
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::StoreCurrentPPSId
+// Stores the PPS id of passed frame for later use
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::StoreCurrentPPSId( TDes8& aNalBuf )
+{
+ TUint8* bufferPtr = (TUint8*)(aNalBuf.Ptr());
+ TUint bufferLength = aNalBuf.Length();
+
+ switch (iNalLengthSize)
+ {
+ case 1:
+ bufferLength = bufferPtr[0];
+ bufferPtr += 1;
+ break;
+ case 2:
+ bufferLength = (bufferPtr[0] << 8) + bufferPtr[1];
+ bufferPtr += 2;
+ break;
+ case 4:
+ bufferLength = (bufferPtr[0] << 24) + (bufferPtr[1] << 16) +
+ (bufferPtr[2] << 8) + bufferPtr[3];
+
+ bufferPtr += 4;
+ break;
+ }
+ avcdStoreCurrentPPSId(iAvcDecoder, bufferPtr, bufferLength);
+}
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::GenerateNotCodedFrame
+// Generates a not coded (empty) frame
+// ---------------------------------------------------------
+//
+TInt CVedAVCEditImp::GenerateNotCodedFrame( TDes8& aNalBuf, TUint aFrameNumber )
+{
+ TUint8* bufferPtr = (TUint8*)(aNalBuf.Ptr());
+ TUint bufferLength = aNalBuf.Length();
+ TInt frameLength = 0;
+
+ frameLength = avcdGenerateNotCodedFrame(iAvcDecoder, bufferPtr, bufferLength, aFrameNumber);
+
+ if(frameLength > 0)
+ {
+ TInt i;
+
+ // Make room for iNalLengthSize bytes of length information to the start
+ for (i=frameLength-1; i>=0; i--)
+ {
+ bufferPtr[i+iNalLengthSize] = bufferPtr[i];
+ }
+
+ // Add the NAL size information to the buffer
+ switch (iNalLengthSize)
+ {
+ case 1:
+ bufferPtr[0] = TUint8(frameLength & 0xff);
+ frameLength++;
+ break;
+ case 2:
+ bufferPtr[0] = TUint8((frameLength >> 8) & 0xff);
+ bufferPtr[1] = TUint8(frameLength & 0xff);
+ frameLength += 2;
+ break;
+ case 4:
+ bufferPtr[0] = TUint8((frameLength >> 24) & 0xff);
+ bufferPtr[1] = TUint8((frameLength >> 16) & 0xff);
+ bufferPtr[2] = TUint8((frameLength >> 8) & 0xff);
+ bufferPtr[3] = TUint8(frameLength & 0xff);
+ frameLength += 4;
+ break;
+ }
+
+ return frameLength;
+ }
+ else
+ return 0;
+}
+
+// ---------------------------------------------------------
+// CVedAVCEditImp::ModifyFrameNumber
+// Modifies the frame number of input NAL unit
+// ---------------------------------------------------------
+//
+void CVedAVCEditImp::ModifyFrameNumber( TDes8& aNalBuf, TUint aFrameNumber )
+{
+ TUint8* bufferPtr = (TUint8*)(aNalBuf.Ptr());
+ TUint bufferLength = aNalBuf.Length();
+
+ switch (iNalLengthSize)
+ {
+ case 1:
+ bufferLength = bufferPtr[0];
+ bufferPtr += 1;
+ break;
+ case 2:
+ bufferLength = (bufferPtr[0] << 8) + bufferPtr[1];
+ bufferPtr += 2;
+ break;
+ case 4:
+ bufferLength = (bufferPtr[0] << 24) + (bufferPtr[1] << 16) +
+ (bufferPtr[2] << 8) + bufferPtr[3];
+
+ bufferPtr += 4;
+ break;
+ }
+
+ if (bufferPtr[0]==0x01 && bufferPtr[1]==0x42)
+ return;
+
+ avcdModifyFrameNumber(iAvcDecoder, bufferPtr, bufferLength, aFrameNumber);
+}
+
+#endif
+
+// End of file
+
+