--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/VedVolReader.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,889 @@
+/*
+* 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:
+* MPEG-4 VOL header parsing.
+*
+*/
+
+
+// INCLUDE FILES
+#include "mpegcons.h"
+#include "VedVolReader.h"
+
+
+
+// MACROS
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x;
+#else
+#define PRINT(x)
+#endif
+
+
+
+// CONSTANTS
+const TUint8 CVedVolReader::KMsbMask[] = {1, 3, 7, 15, 31, 63, 127, 255};
+const TUint8 CVedVolReader::KLsbMask[] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
+
+const TInt CVedVolReader::KMaxUserDataLength = 512;
+
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// Two-phased constructor
+EXPORT_C CVedVolReader* CVedVolReader::NewL()
+ {
+ CVedVolReader* self = new (ELeave) CVedVolReader();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+// C++ default constructor
+CVedVolReader::CVedVolReader() : iBitstreamMode(EVedVideoBitstreamModeUnknown)
+ {
+ // Reset the header data to zeroes
+ Mem::FillZ(&iHeader, sizeof(TVolHeader));
+ }
+
+// Symbian OS default constructor can leave
+void CVedVolReader::ConstructL()
+ {
+ }
+
+// Destructor
+CVedVolReader::~CVedVolReader()
+ {
+ if (iHeader.iUserData != 0)
+ {
+ delete iHeader.iUserData;
+ }
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::ParseVolHeaderL
+// Parses given Video Object Layer header
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::ParseVolHeaderL(TDesC8& aData)
+ {
+ TInt useDefaultVBVParams = 0;
+ TInt numBits;
+ TUint32 bits;
+
+ // Reset the header data
+ if (iHeader.iUserData != 0)
+ {
+ delete iHeader.iUserData;
+ iHeader.iUserData = 0;
+ }
+ Mem::FillZ(&iHeader, sizeof(TVolHeader));
+ iBitstreamMode = EVedVideoBitstreamModeUnknown;
+ iHeaderSize = 0;
+
+ // Check that we have something to parse
+ if (aData.Length() == 0)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ TSeqHeaderBuffer buffer(aData, 0, 7); // Bit 7 is the first bit in a byte
+
+ // if H.263 PSC is present
+ bits = ReadSeqHeaderBits(buffer, 22, EFalse);
+ if (bits == 32)
+ {
+ // This is H.263 so there are no VOL headers
+ iBitstreamMode = EVedVideoBitstreamModeH263;
+ return KErrNone;
+ }
+
+ // if Visual Object Sequence Start Code is present
+ bits = ReadSeqHeaderBits(buffer, MP4_VOS_START_CODE_LENGTH, EFalse);
+ if (bits == MP4_VOS_START_CODE)
+ {
+ // vos_start_code
+ ReadSeqHeaderBits(buffer, MP4_VOS_START_CODE_LENGTH, ETrue);
+
+ // profile_and_level_indication (8 bits)
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ // 8: Simple Profile Level 0 (from ISO/IEC 14496-2:1999/FPDAM4 [N3670] October 2000)
+ // 9: Simple Profile Level 0b
+ // 1: Simple Profile Level 1
+ // 2: Simple Profile Level 2
+ // 3: Simple Profile Level 3
+ // 4: Simple Profile Level 4a
+ if (bits != 1 && bits != 2 && bits != 3 && bits != 4 && bits != 8 && bits != 9)
+ {
+ // Profile level id was not recognized so take a guess
+ // This is changed later if resolution does not match
+ bits = 9;
+ }
+
+ iHeader.iProfileLevelId = (TInt) bits;
+
+ ReadUserDataL(buffer);
+ }
+
+ // if Visual Object Start Code is present
+ bits = ReadSeqHeaderBits(buffer, MP4_VO_START_CODE_LENGTH, EFalse);
+ if (bits == MP4_VO_START_CODE)
+ {
+ // visual_object_start_code
+ ReadSeqHeaderBits(buffer, MP4_VO_START_CODE_LENGTH, ETrue);
+
+ // is_visual_object_identifier (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ // visual_object_ver_id (4 bits)
+ bits = ReadSeqHeaderBits(buffer, 4, ETrue);
+ if (bits != 1 && bits != 2)
+ {
+ // this is not an MPEG-4 version 1 or 2 stream
+ PRINT((_L("CVedVolReader: ERROR - This is not an MPEG-4 version 1 or 2 stream")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // visual_object_priority (3 bits)
+ bits = ReadSeqHeaderBits(buffer, 3, ETrue);
+ iHeader.iVoPriority = (TInt) bits;
+ }
+ else
+ {
+ iHeader.iVoPriority = 0;
+ }
+
+ // visual_object_type (4 bits)
+ bits = ReadSeqHeaderBits(buffer, 4, ETrue);
+ if (bits != 1)
+ {
+ // this is not a video object
+ PRINT((_L("CVedVolReader: ERROR - This is not a video object")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // is_video_signal_type (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ /* Note: The following fields in the bitstream give information about the
+ video signal type before encoding. These parameters don't influence the
+ decoding algorithm, but the composition at the output of the video decoder.
+ Until a way to utilize them is found, these fields are just dummyly read,
+ but not interpreted.
+ For interpretation see the MPEG-4 Visual standard page 66-70. */
+
+ // video_format (3 bits)
+ bits = ReadSeqHeaderBits(buffer, 3, ETrue);
+ iHeader.iVideoFormat = (TInt) bits;
+
+ // video_range (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ iHeader.iVideoRange = (TInt) bits;
+
+ // colour_description (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ // colour_primaries (8 bits)
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ iHeader.iColourPrimaries = (TInt) bits;
+
+ // transfer_characteristics (8 bits)
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ iHeader.iTransferCharacteristics = (TInt) bits;
+
+ // matrix_coefficients (8 bits)
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ iHeader.iMatrixCoefficients = (TInt) bits;
+ }
+ else
+ {
+ iHeader.iColourPrimaries = 1; // default: ITU-R BT.709
+ iHeader.iTransferCharacteristics = 1; // default: ITU-R BT.709
+ iHeader.iMatrixCoefficients = 1; // default: ITU-R BT.709
+ }
+ }
+ else
+ {
+ // default values
+ iHeader.iVideoFormat = 5; // Unspecified video format
+ iHeader.iVideoRange = 0; // Y range 16-235 pixel values
+ iHeader.iColourPrimaries = 1; // ITU-R BT.709
+ iHeader.iTransferCharacteristics = 1; // ITU-R BT.709
+ iHeader.iMatrixCoefficients = 1; // ITU-R BT.709
+ }
+
+ // check the next start code
+ ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (buffer.iBitInOctet != 7)
+ {
+ numBits = buffer.iBitInOctet + 1;
+
+ bits = ReadSeqHeaderBits(buffer, numBits, ETrue);
+ if (bits != (TUint32) ((1 << numBits)-1))
+ {
+ // stuffing error in VO
+ PRINT((_L("CVedVolReader: ERROR - Stuffing error")))
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ ReadUserDataL(buffer);
+ }
+
+ // if Video Object Start Code is present
+ bits = ReadSeqHeaderBits(buffer, MP4_VID_START_CODE_LENGTH, EFalse);
+ if (bits == MP4_VID_START_CODE)
+ {
+ // video_object_start_code
+ ReadSeqHeaderBits(buffer, MP4_VID_START_CODE_LENGTH, ETrue);
+
+ // video_object_id
+ bits = ReadSeqHeaderBits(buffer, MP4_VID_ID_CODE_LENGTH, ETrue);
+ iHeader.iVoId = (TInt) bits;
+ }
+
+ // Check if H.263 PSC follows the VO header, in which case this is MPEG-4 with short header
+ bits = ReadSeqHeaderBits(buffer, 22, EFalse);
+ if (bits == 32 || buffer.iData.Length() <= buffer.iGetIndex)
+ {
+ iBitstreamMode = EVedVideoBitstreamModeMPEG4ShortHeader;
+
+ // Calculate the header size in bytes
+ if (buffer.iBitInOctet == 7)
+ {
+ // The size is a multiple of 8 bits so the size is the number of bytes we've read so far
+ iHeaderSize = buffer.iGetIndex;
+ }
+ else
+ {
+ // Round up to the next full byte
+ iHeaderSize = buffer.iGetIndex + 1;
+ }
+
+ // We no longer support short header clips
+ User::Leave(KErrNotSupported);
+ }
+
+ // vol_start_code
+ bits = ReadSeqHeaderBits(buffer, MP4_VOL_START_CODE_LENGTH, ETrue);
+ if(bits != MP4_VOL_START_CODE)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Bitstream does not start with MP4_VOL_START_CODE")))
+ User::Leave(KErrCorrupt);
+ }
+
+ // vol_id
+ bits = ReadSeqHeaderBits(buffer, MP4_VOL_ID_CODE_LENGTH, ETrue);
+ iHeader.iVolId = (TInt) bits;
+
+ // random_accessible_vol (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ iHeader.iRandomAccessibleVol = (TUint8) bits;
+
+ // video_object_type_indication (8 bits)
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ if (bits != 1)
+ {
+ // this is not a simple video object stream
+ PRINT((_L("CVedVolReader: ERROR - This is not a simple video object stream")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // is_object_layer_identifier (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ // visual_object_ver_id (4 bits)
+ bits = ReadSeqHeaderBits(buffer, 4, ETrue);
+ if (bits != 1 && bits != 2)
+ {
+ // this is not an MPEG-4 version 1 or 2 stream
+ PRINT((_L("CVedVolReader: ERROR - This is not an MPEG-4 version 1 or 2 stream")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // video_object_layer_priority (3 bits)
+ bits = ReadSeqHeaderBits(buffer, 3, ETrue);
+ iHeader.iVoPriority = (TInt) bits;
+ }
+
+ // aspect_ratio_info: `0010`- 12:11 (625-type for 4:3 picture)
+ bits = ReadSeqHeaderBits(buffer, 4, ETrue);
+ iHeader.iPixelAspectRatio = (TInt) bits;
+
+ // extended par
+ if (bits == 15)
+ {
+ // par_width
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ // par_height
+ bits = ReadSeqHeaderBits(buffer, 8, ETrue);
+ }
+
+ // vol_control_parameters flag
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ // chroma_format (2 bits)
+ bits = ReadSeqHeaderBits(buffer, 2, ETrue);
+ if (bits != 1)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Not supported chroma format")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // low_delay (1 bits)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+
+ // vbv_parameters (1 bits)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ // first_half_bitrate (15 bits)
+ bits = ReadSeqHeaderBits(buffer, 15, ETrue);
+ iHeader.iBitRate = (bits << 15);
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // latter_half_bitrate (15 bits)
+ bits = ReadSeqHeaderBits(buffer, 15, ETrue);
+ iHeader.iBitRate += bits;
+ iHeader.iBitRate *= 400;
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // first_half_vbv_buffer_size (15 bits)
+ bits = ReadSeqHeaderBits(buffer, 15, ETrue);
+ iHeader.iVbvBufferSize = (bits << 3);
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // latter_half_vbv_buffer_size (3 bits)
+ bits = ReadSeqHeaderBits(buffer, 3, ETrue);
+ iHeader.iVbvBufferSize += bits;
+ iHeader.iVbvBufferSize *= 16384;
+
+ // first_half_vbv_occupancy (11 bits)
+ bits = ReadSeqHeaderBits(buffer, 11, ETrue);
+ iHeader.iVbvOccupancy = (bits << 15);
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // latter_half_vbv_occupancy (15 bits)
+ bits = ReadSeqHeaderBits(buffer, 15, ETrue);
+ iHeader.iVbvOccupancy += bits;
+ iHeader.iVbvOccupancy *= 64;
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ else
+ {
+ useDefaultVBVParams = 1;
+ }
+ }
+ else
+ {
+ useDefaultVBVParams = 1;
+ }
+
+ // vol_shape (2 bits)
+ bits = ReadSeqHeaderBits(buffer, 2, ETrue);
+ // rectangular_shape = '00'
+ if (bits != 0)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Not rectangular shape is not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // time_increment_resolution
+ bits = ReadSeqHeaderBits(buffer, 16, ETrue);
+ iHeader.iTimeIncrementResolution = (TInt) bits;
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // fixed_vop_rate
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+
+ // fixed_vop_time_increment (1-15 bits)
+ if (bits)
+ {
+ for (numBits = 1; ((iHeader.iTimeIncrementResolution-1) >> numBits) != 0; numBits++)
+ {
+ }
+
+ bits = ReadSeqHeaderBits(buffer, numBits, ETrue);
+ }
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // vol_width (13 bits)
+ bits = ReadSeqHeaderBits(buffer, 13, ETrue);
+ iHeader.iLumWidth = (TInt) bits;
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // vol_height (13 bits)
+ bits = ReadSeqHeaderBits(buffer, 13, ETrue);
+ iHeader.iLumHeight = (TInt) bits;
+
+ // Accept only resolutions that are divisible by 16
+ if ( ((iHeader.iLumWidth & 0x0000000f) != 0) ||
+ ((iHeader.iLumHeight & 0x0000000f) != 0) )
+ {
+ PRINT((_L("CVedVolReader: ERROR - Unsupported resolution")))
+ User::Leave(KErrNotSupported);
+ }
+
+ TInt macroBlocks = iHeader.iLumWidth * iHeader.iLumHeight / (16 * 16);
+
+ // Check that we don't have too many macro blocks (ie resolution is not too big)
+ if( macroBlocks > 1200 )
+ {
+ PRINT((_L("CVedVolReader: ERROR - Unsupported resolution")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // Check that profile level id matches with the number of macro blocks
+ if( macroBlocks > 396 )
+ {
+ // Resolution is higher than CIF => level must be 4a
+ if( iHeader.iProfileLevelId != 4 )
+ {
+ iHeader.iProfileLevelId = 4;
+ useDefaultVBVParams = 1;
+ }
+ }
+ else if( macroBlocks > 99 )
+ {
+ // Resolution is higher than QCIF => level must be atleast 2
+ if( iHeader.iProfileLevelId < 2 || iHeader.iProfileLevelId > 4 )
+ {
+ iHeader.iProfileLevelId = 3; // QVGA/CIF @ 30fps
+ useDefaultVBVParams = 1;
+ }
+ }
+
+ // Set default VBV params if not set already
+ if (useDefaultVBVParams)
+ {
+ switch (iHeader.iProfileLevelId)
+ {
+ case 1:
+ iHeader.iVbvBufferSize = 10;
+ iHeader.iBitRate = 64;
+ break;
+ case 2:
+ iHeader.iVbvBufferSize = 20;
+ iHeader.iBitRate = 128;
+ break;
+ case 4:
+ iHeader.iVbvBufferSize = 80;
+ iHeader.iBitRate = 4000;
+ break;
+ case 8:
+ iHeader.iVbvBufferSize = 10;
+ iHeader.iBitRate = 64;
+ break;
+ case 9:
+ iHeader.iVbvBufferSize = 20;
+ iHeader.iBitRate = 128;
+ break;
+ default:
+ iHeader.iVbvBufferSize = 20;
+ iHeader.iBitRate = 384;
+ break;
+ }
+
+ iHeader.iVbvOccupancy = iHeader.iVbvBufferSize * 170;
+
+ iHeader.iVbvOccupancy *= 64;
+ iHeader.iVbvBufferSize *= 16384;
+ iHeader.iBitRate *= 1024;
+ }
+
+ // marker_bit
+ if (!ReadSeqHeaderBits(buffer, 1, ETrue))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // interlaced (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Interlaced VOP not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // OBMC_disable
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (!bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Overlapped motion compensation not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // sprite_enable (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Sprites not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // not_8_bit (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Not 8 bits/pixel not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // quant_type (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - H.263/MPEG-2 Quant Table switch not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // complexity_estimation_disable (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (!bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Complexity estimation header not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // resync_marker_disable (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ iHeader.iErrorResDisable = (TUint8) bits;
+
+ // data_partitioned (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ iHeader.iDataPartitioned = (TUint8) bits;
+
+ if (iHeader.iDataPartitioned)
+ {
+ // reversible_vlc (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ iHeader.iReversibleVlc = (TUint8) bits;
+ }
+
+ // scalability (1 bit)
+ bits = ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (bits)
+ {
+ PRINT((_L("CVedVolReader: ERROR - Scalability not supported")))
+ User::Leave(KErrNotSupported);
+ }
+
+ // check the next start code
+ ReadSeqHeaderBits(buffer, 1, ETrue);
+ if (buffer.iBitInOctet != 7)
+ {
+ numBits = buffer.iBitInOctet + 1;
+
+ bits = ReadSeqHeaderBits(buffer, numBits, ETrue);
+
+ /* Removed temporarily
+ if (bits != (TUint32) ((1 << numBits)-1))
+ {
+ // this is not a video object
+ PRINT((_L("CVedVolReader: ERROR - Stuffing error")))
+ User::Leave(KErrNotSupported);
+ }*/
+ }
+
+ ReadUserDataL(buffer);
+
+ // Calculate the header size in bytes
+ if (buffer.iBitInOctet == 7)
+ {
+ // The size is a multiple of 8 bits so the size is the number of bytes we've read so far
+ iHeaderSize = buffer.iGetIndex;
+ }
+ else
+ {
+ // Round up to the next full byte
+ iHeaderSize = buffer.iGetIndex + 1;
+ }
+
+ // Determine the bitstream mode
+ iBitstreamMode = CheckBitstreamMode(iHeader.iErrorResDisable, iHeader.iDataPartitioned, iHeader.iReversibleVlc);
+
+ // If no error in bit buffer functions
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::ReadSeqHeaderBits
+// Reads requested bits from given buffer
+// ---------------------------------------------------------
+//
+TUint32 CVedVolReader::ReadSeqHeaderBits(TSeqHeaderBuffer& aBuffer, TInt aNumBits, TBool aFlush)
+ {
+ TUint startIndex; // the index of the first byte to read
+ TUint startMask; // the mask for the first byte
+ TUint endIndex; // the index of the last byte to read
+ TUint endMask; // the mask for the last byte
+ TUint endShift; // the number of shifts after masking the last byte
+ TUint endNumberOfBits; // the number of bits in the last byte
+ TUint newBitIndex; // bitIndex after getting the bits
+ TUint newGetIndex; // getIndex after getting the bits
+
+ TUint32 returnValue = 0;
+
+ startIndex = aBuffer.iGetIndex;
+ startMask = KMsbMask[aBuffer.iBitInOctet];
+
+ // Check that there are enough bits left
+ if (startIndex * 8 + aNumBits > aBuffer.iData.Length() * 8)
+ {
+ return 0;
+ }
+
+ if (aBuffer.iBitInOctet + 1 >= aNumBits)
+ {
+ // The bits are within one byte.
+ endShift = aBuffer.iBitInOctet - aNumBits + 1;
+ endMask = KLsbMask[endShift];
+ returnValue = (aBuffer.iData[startIndex] & startMask & endMask) >> endShift;
+ if (endShift > 0)
+ {
+ newBitIndex = aBuffer.iBitInOctet - aNumBits;
+ newGetIndex = aBuffer.iGetIndex;
+ }
+ else
+ {
+ newBitIndex = 7;
+ newGetIndex = aBuffer.iGetIndex + 1;
+ }
+ }
+ else
+ {
+ // The bits are in multiple bytes.
+ aNumBits -= aBuffer.iBitInOctet + 1;
+ endNumberOfBits = aNumBits & 7;
+
+ newBitIndex = 7 - endNumberOfBits;
+ newGetIndex = aBuffer.iGetIndex + (aNumBits >> 3) + 1;
+
+ // Calculate the return value.
+ endIndex = newGetIndex;
+ endShift = 8 - (aNumBits & 7);
+ endMask = KLsbMask[endShift];
+
+ returnValue = aBuffer.iData[startIndex] & startMask;
+ startIndex++;
+
+ while (startIndex != endIndex)
+ {
+ returnValue <<= 8;
+ returnValue += (TUint8) aBuffer.iData[startIndex];
+ startIndex++;
+ }
+
+ if (endNumberOfBits != 0)
+ {
+ returnValue <<= endNumberOfBits;
+ returnValue += (aBuffer.iData[startIndex] & endMask) >> endShift;
+ }
+ }
+
+ if (aFlush)
+ {
+ // Update indexes.
+ aBuffer.iGetIndex = newGetIndex;
+ aBuffer.iBitInOctet = newBitIndex;
+ }
+
+ return returnValue;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::ReadUserDataL
+// Reads user data from given buffer
+// ---------------------------------------------------------
+//
+void CVedVolReader::ReadUserDataL(TSeqHeaderBuffer& aBuffer)
+ {
+ TUint32 bits;
+
+ // Check if User data is available
+ bits = ReadSeqHeaderBits(aBuffer, 32, EFalse);
+ if (bits == MP4_USER_DATA_START_CODE)
+ {
+ if (iHeader.iUserData == 0)
+ {
+ iHeader.iUserData = HBufC8::NewL(KMaxUserDataLength);
+ }
+
+ TInt i = iHeader.iUserData->Length();
+ do
+ {
+ bits = ReadSeqHeaderBits(aBuffer, 8, ETrue);
+ if (i++ < KMaxUserDataLength)
+ {
+ (iHeader.iUserData->Des()).Append(TChar(bits));
+ }
+ }
+ while (aBuffer.iData.Length() > aBuffer.iGetIndex &&
+ ReadSeqHeaderBits(aBuffer, 24, EFalse) != 0x1);
+ }
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::CheckBitstreamMode
+// Checks what is the bit stream mode the video
+// ---------------------------------------------------------
+//
+TVedVideoBitstreamMode CVedVolReader::CheckBitstreamMode(TUint8 aErd, TUint8 aDp, TUint8 aRvlc)
+ {
+ TVedVideoBitstreamMode mode = EVedVideoBitstreamModeUnknown;
+ int combination = ((!aErd) << 2) | (aDp << 1) | aRvlc;
+
+ switch (combination)
+ {
+ case 0:
+ mode = EVedVideoBitstreamModeMPEG4Regular;
+ break;
+ case 2:
+ mode = EVedVideoBitstreamModeMPEG4DP;
+ break;
+ case 3:
+ mode = EVedVideoBitstreamModeMPEG4DP_RVLC;
+ break;
+ case 4:
+ mode = EVedVideoBitstreamModeMPEG4Resyn;
+ break;
+ case 6:
+ mode = EVedVideoBitstreamModeMPEG4Resyn_DP;
+ break;
+ case 7:
+ mode = EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC;
+ break;
+ default:
+ break;
+ }
+
+ return mode;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::TimeIncrementResolution
+// Returns the time increment resolution that was read from the VOL header
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::TimeIncrementResolution() const
+ {
+ return iHeader.iTimeIncrementResolution;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::Width
+// Returns the width of the video that was read from the VOL header
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::Width() const
+ {
+ return iHeader.iLumWidth;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::Height
+// Returns the height of the video that was read from the VOL header
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::Height() const
+ {
+ return iHeader.iLumHeight;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::ProfileLevelId
+// Returns the Level Id of the Simple Profile the Video Object conforms to
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::ProfileLevelId() const
+ {
+ return iHeader.iProfileLevelId;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::BitstreamMode
+// Returns the bitstream mode of the video
+// ---------------------------------------------------------
+//
+EXPORT_C TVedVideoBitstreamMode CVedVolReader::BitstreamMode() const
+ {
+ return iBitstreamMode;
+ }
+
+// ---------------------------------------------------------
+// CVedVolReader::HeaderSize
+// Returns the bitstream mode of the video
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CVedVolReader::HeaderSize() const
+ {
+ return iHeaderSize;
+ }
+