[datatype-dev] CR-RESEND: Parse H.264 opaque data (fix for 244230)

[datatype-dev] CR-RESEND: Parse H.264 opaque data (fix for 244230)

Eric Hyche ehyche at real.com
Mon Jun 29 06:18:57 PDT 2009


Please review.

=======================================
Eric Hyche (ehyche at real.com)
Principal Engineer
RealNetworks, Inc.


>-----Original Message-----
>From: datatype-dev-bounces at helixcommunity.org [mailto:datatype-dev-bounces at helixcommunity.org] On
>Behalf Of Eric Hyche
>Sent: Thursday, June 25, 2009 4:50 PM
>To: datatype-dev at lists.helixcommunity.org
>Subject: [datatype-dev] CR: Parse H.264 opaque data (fix for 244230)
>
>Description
>-------------------------------------------
>The MainConcept-based and the QT-based H.264 decoders need to be able to recover the width and height
>of the encoded stream before having to create a buffer to be decoded into. So we add code in
>datatype/h264/common to parse the Sequence Parameter Set in the AVCDecoderConfigurationRecord and
>recover the width and height from there. Then we use this code in the QT-based H.264 decoder. (Changes
>for the MC-based decoder are sent separately.)
>
>Files Modified
>-------------------------------------------
>datatype/h264/codec/decoder_qtsdk/Umakefil
>datatype/h264/codec/decoder_qtsdk/platform/win/h264qt.cpp
>datatype/h264/codec/decoder_qtsdk/platform/win/h264qt.h
>datatype/h264/common/hx_parse_h264.cpp
>datatype/h264/common/pub/hx_parse_h264.h
>
>Branches
>-------------------------------------------
>HEAD, 310Atlas, and 204Cay
>
>
>=======================================
>Eric Hyche (ehyche at real.com)
>Principal Engineer
>RealNetworks, Inc.
>

-------------- next part --------------
Index: Umakefil
===================================================================
RCS file: /cvsroot/datatype/h264/codec/decoder_qtsdk/Umakefil,v
retrieving revision 1.1
diff -u -w -u -w -r1.1 Umakefil
--- Umakefil	14 Jan 2009 19:13:47 -0000	1.1
+++ Umakefil	25 Jun 2009 19:42:42 -0000
@@ -73,7 +73,8 @@
                            "common/util[utillib]",
                            "datatype/common/util[dtutillib]",
                            "common/runtime[runtlib]",
-                           "common/log/logutil[logutillib]")
+                           "common/log/logutil[logutillib]",
+                           "datatype/h264/common[h264comlib]")
 
 project.ExportFunction("PNCodec_Open",
                        "HX_MOFTAG moftFormatTag,HXCODEC *codecRef",
Index: platform/win/h264qt.cpp
===================================================================
RCS file: /cvsroot/datatype/h264/codec/decoder_qtsdk/platform/win/h264qt.cpp,v
retrieving revision 1.5
diff -u -w -u -w -r1.5 h264qt.cpp
--- platform\win\h264qt.cpp	22 May 2009 16:05:12 -0000	1.5
+++ platform\win\h264qt.cpp	25 Jun 2009 19:42:42 -0000
@@ -65,6 +65,7 @@
 #include "pckunpck.h"
 #include "hxpacketflags.h"
 #include "h264qt.h"
+#include "hx_parse_h264.h"
 #include "ImageCompression.h" // from QuickTime SDK
 #include "GXMath.h"
 
@@ -443,6 +444,31 @@
             // Get the opaque data pointer and the opaque data size
             BYTE*  pOpaqueData      = ((BYTE*) pParams->pInMof) + 12;
             UINT32 ulOpaqueDataSize = pParams->pInMof->cbLength - 12;
+            // Parse the opaque data
+            HXAVCDecoderConfigurationRecord record;
+            HX_RESULT rv = record.Unpack(pOpaqueData, ulOpaqueDataSize);
+            if (SUCCEEDED(rv))
+            {
+                // Get the width and height
+                UINT32 ulWidth  = 0;
+                UINT32 ulHeight = 0;
+                rv = record.GetLumaWidthHeight(&ulWidth, &ulHeight);
+                if (SUCCEEDED(rv) && !m_ulFrameWidth && !m_ulFrameHeight)
+                {
+                    // Save the width and height
+                    m_ulFrameWidth  = ulWidth;
+                    m_ulFrameHeight = ulHeight;
+                    // QTSDK tends to give us back frames which have
+                    // a width that is a multiple of 16. So if the
+                    // width is not a multiple of 16, then round up
+                    // to the next multiple of 16.
+                    UINT32 ulRem = m_ulFrameWidth % 16;
+                    if (ulRem)
+                    {
+                        m_ulFrameWidth += 16 - ulRem;
+                    }
+                }
+            }
             // The initialization data passed in is the sample description
             // from the stsd box. In most cases, this is the CONTENTS
             // of the 'avcC' box as defined in the MPEG-4 AVC spec.
@@ -944,8 +970,75 @@
 
 HX_RESULT CHXH264StreamQT::PNStream_GetProperty(ULONG32 ulProp, void* pValue)
 {
-    HX_ASSERT(FALSE && "CHXH264StreamQT::PNStream_GetProperty() not implemented.");
-    return HXR_NOTIMPL;
+    HXLOGL4(HXLOG_AVCQ, "CHXH264StreamQT[%p]::PNStream_GetProperty(%lu,)", this, ulProp);
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pValue)
+    {
+        // Clear the return value
+        retVal = HXR_OK;
+        // Switch on property type
+        switch (ulProp)
+        {
+            case SP_OUPUT_QUEUE_STATUS:
+                {
+                    memcpy(pValue, &m_OutputQueueStatus, sizeof(HX_OQS));
+                }
+                break;
+            case SP_OUPUT_QUEUE_STATUS2:
+                {
+                    memcpy(pValue, &m_OutputQueueStatus2, sizeof(HX_OQS2));
+                }
+                break;
+            case SP_ALLOW_DIFFERENT_OUPUT_SIZES:
+                {
+                    *((HXBOOL*) pValue) = m_bAllowDifferentOutputSizes;
+                }
+                break;
+            case SP_CPUSCALABILITY:
+                {
+                    *((HXBOOL*) pValue) = m_bCPUScalability;
+                }
+                break;
+            case SP_POSTFILTER:
+                {
+                    *((HXBOOL*) pValue) = m_bPostFilter;
+                }
+                break;
+            case SP_TEMPORALINTERP:
+                {
+                    *((HXBOOL*) pValue) = m_bTemporalInterpolation;
+                }
+                break;
+            case SP_DECODE_B_FRAMES:
+                {
+                    *((HXBOOL*) pValue) = m_bDecodeBFrames;
+                }
+                break;
+            case SP_FRAME_WIDTH:
+                {
+                    *((UINT32*) pValue) = m_ulFrameWidth;
+                }
+                break;
+            case SP_FRAME_HEIGHT:
+                {
+                    *((UINT32*) pValue) = m_ulFrameHeight;
+                }
+                break;
+            case SP_HWMEM_MGT:
+                {
+                    *((HXBOOL*) pValue) = FALSE;
+                }
+                break;
+            default:
+                {
+                    retVal = HXR_FAIL;
+                }
+                break;
+        }
+    }
+
+    return retVal;
 }
 
 #if defined(HW_VIDEO_MEMORY_FRONTEND)
Index: hx_parse_h264.cpp
===================================================================
RCS file: /cvsroot/datatype/h264/common/hx_parse_h264.cpp,v
retrieving revision 1.1
diff -u -w -u -w -r1.1 hx_parse_h264.cpp
--- hx_parse_h264.cpp	20 May 2009 13:25:01 -0000	1.1
+++ hx_parse_h264.cpp	25 Jun 2009 19:42:55 -0000
@@ -60,6 +60,353 @@
 #include "pckunpck.h"
 #include "hx_parse_h264.h"
 
+const BYTE g_ucDefault_4x4_Intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42};
+const BYTE g_ucDefault_4x4_Inter[16] = {10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34};
+const BYTE g_ucDefault_8x8_Intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
+                                        23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
+                                        27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
+                                        31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42};
+const BYTE g_ucDefault_8x8_Inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
+                                        21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
+                                        24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
+                                        27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35};
+
+HX_RESULT HXAVCSequenceParameterSet::Unpack(BYTE* pBuf, UINT32 ulLen)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pBuf && ulLen)
+    {
+        // Set the return value
+        retVal = HXR_FAIL;
+        // Make sure we have enough bytes
+        if (ulLen >= 3)
+        {
+            UINT32 i = 0;
+            // Unpack the profile_idc
+            UnpackUINT8Inc(&pBuf, &ulLen, &m_ucProfileIDC);
+            // Unpack the constaint flags
+            BYTE ucTmp = 0;
+            UnpackUINT8Inc(&pBuf, &ulLen, &ucTmp);
+            m_bConstraintSet0Flag = ((ucTmp & 0x80) ? TRUE : FALSE);
+            m_bConstraintSet1Flag = ((ucTmp & 0x40) ? TRUE : FALSE);
+            m_bConstraintSet2Flag = ((ucTmp & 0x20) ? TRUE : FALSE);
+            m_bConstraintSet3Flag = ((ucTmp & 0x10) ? TRUE : FALSE);
+            // Unpack the level_idc
+            UnpackUINT8Inc(&pBuf, &ulLen, &m_ucLevelIDC);
+            // Set up the Bitstream class
+            Bitstream bs;
+            bs.SetBuffer(pBuf, ulLen);
+            // Parse the seq_parameter_set_id
+            retVal = ParseExpGolombUnsigned(&bs, &m_ulSeqParameterSetID);
+            if (SUCCEEDED(retVal))
+            {
+                // Check profile_idc
+                if (m_ucProfileIDC == 100 || m_ucProfileIDC == 110 ||
+                    m_ucProfileIDC == 122 || m_ucProfileIDC == 244 ||
+                    m_ucProfileIDC ==  44 || m_ucProfileIDC ==  83 ||
+                    m_ucProfileIDC ==  86)
+                {
+                    // Parse the chroma_format_idc
+                    retVal = ParseExpGolombUnsigned(&bs, &m_ulChromaFormatIDC);
+                    if (SUCCEEDED(retVal))
+                    {
+                        // If the chroma_format_idc is 3, then we need to get the separate_colour_plane_flag
+                        if (m_ulChromaFormatIDC == 3)
+                        {
+                            retVal = ParseBitstreamHXBOOL(&bs, &m_bSeparateColourPlaneFlag);
+                        }
+                        if (SUCCEEDED(retVal))
+                        {
+                            // Parse the bit_depth_luma_minus8
+                            retVal = ParseExpGolombUnsigned(&bs, &m_ulBitDepthLumaMinus8);
+                            if (SUCCEEDED(retVal))
+                            {
+                                // Parse the bit_depth_chroma_minus8
+                                retVal = ParseExpGolombUnsigned(&bs, &m_ulBitDepthChromaMinus8);
+                                if (SUCCEEDED(retVal))
+                                {
+                                    // Parse the qpprime_y_zero_transform_bypass_flag
+                                    retVal = ParseBitstreamHXBOOL(&bs, &m_bQPPrimeYZeroTransformBypassFlag);
+                                    if (SUCCEEDED(retVal))
+                                    {
+                                        // Parse the seq_scaling_matrix_present_flag
+                                        retVal = ParseBitstreamHXBOOL(&bs, &m_bSeqScalingMatrixPresentFlag);
+                                        if (SUCCEEDED(retVal))
+                                        {
+                                            // Are scaling matrices present?
+                                            if (m_bSeqScalingMatrixPresentFlag)
+                                            {
+                                                // Compute the number of scaling lists. If the chroma_format_idc is not 3,
+                                                // then there are 8. If chroma_format_idc is 3, then there are 12.
+                                                UINT32 ulNumLists = (m_ulChromaFormatIDC != 3 ? 8 : 12);
+                                                for (i = 0; i < ulNumLists && SUCCEEDED(retVal); i++)
+                                                {
+                                                    // Parse the seq_scaling_list_present_flag[i]
+                                                    retVal = ParseBitstreamHXBOOL(&bs, &m_bSeqScalingListPresent[i]);
+                                                    if (SUCCEEDED(retVal))
+                                                    {
+                                                        // Is the i-th scaling list present?
+                                                        if (m_bSeqScalingListPresent[i])
+                                                        {
+                                                            if (i < 6)
+                                                            {
+                                                                // Parse the 4x4 scaling lists
+                                                                retVal = ParseScalingList(&bs, i, &m_ucScalingList4x4[i][0], 16,
+                                                                                          &m_bUseDefaultScalingMatrix4x4Flag[i]);
+                                                            }
+                                                            else
+                                                            {
+                                                                // Parse the 8x8 scaling lists
+                                                                retVal = ParseScalingList(&bs, i, &m_ucScalingList8x8[i - 6][0], 64,
+                                                                                          &m_bUseDefaultScalingMatrix8x8Flag[i - 6]);
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                if (SUCCEEDED(retVal))
+                {
+                    // Parse the log2_max_frame_num_minus4
+                    retVal = ParseExpGolombUnsigned(&bs, &m_ulLog2MaxFrameNumMinus4);
+                    if (SUCCEEDED(retVal))
+                    {
+                        // Parse the pic_order_cnt_type
+                        retVal = ParseExpGolombUnsigned(&bs, &m_ulPicOrderCntType);
+                        if (SUCCEEDED(retVal))
+                        {
+                            // Switch on pic_order_cnt_type
+                            if (m_ulPicOrderCntType == 0)
+                            {
+                                // Parse the log2_max_pic_order_cnt_lsb_minus4
+                                retVal = ParseExpGolombUnsigned(&bs, &m_ulLog2MaxPicOrderCntLsbMinus4);
+                            }
+                            else if (m_ulPicOrderCntType == 1)
+                            {
+                                // Parse delta_pic_order_always_zero_flag
+                                retVal = ParseBitstreamHXBOOL(&bs, &m_bDeltaPicOrderAlwaysZeroFlag);
+                                if (SUCCEEDED(retVal))
+                                {
+                                    // Parse offset_for_non_ref_pic
+                                    retVal = ParseExpGolombSigned(&bs, &m_lOffsetForNonRefPic);
+                                    if (SUCCEEDED(retVal))
+                                    {
+                                        // Parse offset_for_top_to_bottom_field
+                                        retVal = ParseExpGolombSigned(&bs, &m_lOffsetForTopToBottomField);
+                                        if (SUCCEEDED(retVal))
+                                        {
+                                            // Parse num_ref_frames_in_pic_order_cnt_cycle
+                                            retVal = ParseExpGolombUnsigned(&bs, &m_ulNumRefFramesInPicOrderCntCycle);
+                                            if (SUCCEEDED(retVal))
+                                            {
+                                                // Make sure m_ulNumRefFramesInPicOrderCntCycle is non-zero
+                                                if (m_ulNumRefFramesInPicOrderCntCycle)
+                                                {
+                                                    // Set the return value
+                                                    retVal = HXR_OUTOFMEMORY;
+                                                    // Allocate offset_for_frame_ref array
+                                                    HX_VECTOR_DELETE(m_plOffsetForRefFrame);
+                                                    m_plOffsetForRefFrame = new INT32 [m_ulNumRefFramesInPicOrderCntCycle];
+                                                    if (m_plOffsetForRefFrame)
+                                                    {
+                                                        // Clear the return value
+                                                        retVal = HXR_OK;
+                                                        // Zero out the array
+                                                        memset(m_plOffsetForRefFrame, 0, m_ulNumRefFramesInPicOrderCntCycle * sizeof(INT32));
+                                                        // Loop through reading each offset
+                                                        for (i = 0; i < m_ulNumRefFramesInPicOrderCntCycle && SUCCEEDED(retVal); i++)
+                                                        {
+                                                            // Read offset_for_ref_frame[i]
+                                                            retVal = retVal = ParseExpGolombSigned(&bs, &m_plOffsetForRefFrame[i]);
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (SUCCEEDED(retVal))
+                            {
+                                // Parse num_ref_frames
+                                retVal = ParseExpGolombUnsigned(&bs, &m_ulNumRefFrames);
+                                if (SUCCEEDED(retVal))
+                                {
+                                    // Parse gaps_in_frame_num_value_allowed_flag
+                                    retVal = ParseBitstreamHXBOOL(&bs, &m_bGapsInFrameNumValueAllowedFlag);
+                                    if (SUCCEEDED(retVal))
+                                    {
+                                        // Parse pic_width_in_mbs_minus1
+                                        retVal = ParseExpGolombUnsigned(&bs, &m_ulPicWidthInMbsMinus1);
+                                        if (SUCCEEDED(retVal))
+                                        {
+                                            // Parse pic_height_in_map_units_minus1
+                                            retVal = ParseExpGolombUnsigned(&bs, &m_ulPicHeightInMapUnitsMinus1);
+                                            if (SUCCEEDED(retVal))
+                                            {
+                                                // Parse m_bFrameMbsOnlyFlag
+                                                retVal = ParseBitstreamHXBOOL(&bs, &m_bFrameMbsOnlyFlag);
+                                                if (SUCCEEDED(retVal))
+                                                {
+                                                    if (!m_bFrameMbsOnlyFlag)
+                                                    {
+                                                        // Parse mb_adaptive_frame_field_flag
+                                                        retVal = ParseBitstreamHXBOOL(&bs, &m_bMbAdaptiveFrameFieldFlag);
+                                                    }
+                                                    if (SUCCEEDED(retVal))
+                                                    {
+                                                        // Parse direct_8x8_inference_flag
+                                                        retVal = ParseBitstreamHXBOOL(&bs, &m_bDirect8x8InferenceFlag);
+                                                        if (SUCCEEDED(retVal))
+                                                        {
+                                                            // Parse frame_cropping_flag
+                                                            retVal = ParseBitstreamHXBOOL(&bs, &m_bFrameCroppingFlag);
+                                                            if (SUCCEEDED(retVal))
+                                                            {
+                                                                // Is the frame_cropping_flag set?
+                                                                if (m_bFrameCroppingFlag)
+                                                                {
+                                                                    // Parse frame_crop_left_offset
+                                                                    retVal = ParseExpGolombUnsigned(&bs, &m_ulFrameCropLeftOffset);
+                                                                    if (SUCCEEDED(retVal))
+                                                                    {
+                                                                        // Parse frame_crop_right_offset
+                                                                        retVal = ParseExpGolombUnsigned(&bs, &m_ulFrameCropRightOffset);
+                                                                        if (SUCCEEDED(retVal))
+                                                                        {
+                                                                            // Parse frame_crop_top_offset
+                                                                            retVal = ParseExpGolombUnsigned(&bs, &m_ulFrameCropTopOffset);
+                                                                            if (SUCCEEDED(retVal))
+                                                                            {
+                                                                                // Parse frame_crop_bottom_offset
+                                                                                retVal = ParseExpGolombUnsigned(&bs, &m_ulFrameCropBottomOffset);
+                                                                            }
+                                                                        }
+                                                                    }
+                                                                }
+                                                                else
+                                                                {
+                                                                    // frame_cropping_flag is not set, so offsets are 0
+                                                                    m_ulFrameCropLeftOffset   = 0;
+                                                                    m_ulFrameCropRightOffset  = 0;
+                                                                    m_ulFrameCropTopOffset    = 0;
+                                                                    m_ulFrameCropBottomOffset = 0;
+                                                                }
+                                                                if (SUCCEEDED(retVal))
+                                                                {
+                                                                    // Parse vui_parameters_present_flag
+                                                                    retVal = ParseBitstreamHXBOOL(&bs, &m_bVuiParametersPresentFlag);
+                                                                    if (SUCCEEDED(retVal))
+                                                                    {
+                                                                        // Is vui_parameters() present?
+                                                                        if (m_bVuiParametersPresentFlag)
+                                                                        {
+                                                                            // We do not currently parse the vui_parameters()
+                                                                        }
+                                                                    }
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return retVal;
+}
+
+HX_RESULT HXAVCSequenceParameterSet::GetLumaWidthHeight(UINT32* pulWidth, UINT32* pulHeight)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pulWidth && pulHeight)
+    {
+        // Get the ChromaArrayType
+        UINT32 ulChromaArrayType = (m_bSeparateColourPlaneFlag ? 0 : m_ulChromaFormatIDC);
+        // Get an integer value for m_bFrameMbsOnlyFlag
+        UINT32 ulFrameMbsOnlyFlag = (m_bFrameMbsOnlyFlag ? 1 : 0);
+        // Compute the SubWidthC and SubHeightC values
+        UINT32 ulSubWidthC  = 0;
+        UINT32 ulSubHeightC = 0;
+        if (!m_bSeparateColourPlaneFlag)
+        {
+            switch (m_ulChromaFormatIDC)
+            {
+                case 1:
+                    ulSubWidthC  = 2;
+                    ulSubHeightC = 2;
+                    break;
+                case 2:
+                    ulSubWidthC  = 2;
+                    ulSubHeightC = 1;
+                    break;
+                case 3:
+                    ulSubWidthC  = 1;
+                    ulSubHeightC = 1;
+                    break;
+            }
+        }
+        // Compute the crop units
+        UINT32 ulCropUnitX = 0;
+        UINT32 ulCropUnitY = 0;
+        if (ulChromaArrayType == 0)
+        {
+            ulCropUnitX = 1;
+            ulCropUnitY = 2 - ulFrameMbsOnlyFlag;
+        }
+        else
+        {
+            ulCropUnitX = ulSubWidthC;
+            ulCropUnitY = ulSubHeightC * (2 - ulFrameMbsOnlyFlag);
+        }
+        // Compute the picture width in luma samples
+        UINT32 ulPicWidthInSamplesLuma = (m_ulPicWidthInMbsMinus1 + 1) * 16;
+        // Compute frame height in macroblocks
+        UINT32 ulFrameHeightInMbs = (2 - ulFrameMbsOnlyFlag) * (m_ulPicHeightInMapUnitsMinus1 + 1);
+        // Compute the coordinates
+        UINT32 ulFrameLeftLuma   = m_ulFrameCropLeftOffset * ulCropUnitX;
+        UINT32 ulFrameRightLuma  = ulPicWidthInSamplesLuma - (ulCropUnitX * m_ulFrameCropRightOffset + 1);
+        UINT32 ulFrameTopLuma    = m_ulFrameCropTopOffset * ulCropUnitY;
+        UINT32 ulFrameBottomLuma = (16 * ulFrameHeightInMbs) - (ulCropUnitY * m_ulFrameCropBottomOffset + 1);
+        // Now compute the dimensions
+        *pulWidth  = ((ulFrameLeftLuma <= ulFrameRightLuma) ? (ulFrameRightLuma - ulFrameLeftLuma + 1) : 0);
+        *pulHeight = ((ulFrameTopLuma <= ulFrameBottomLuma) ? (ulFrameBottomLuma - ulFrameTopLuma + 1) : 0);
+        // Clear the return value
+        retVal = HXR_OK;
+    }
+
+    return retVal;
+}
+
+HX_RESULT HXAVCPictureParameterSet::Unpack(BYTE* pBuf, UINT32 ulLen)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pBuf && ulLen)
+    {
+        // We don't currently parse the picture parameter set
+        retVal = HXR_OK;
+    }
+
+    return retVal;
+}
+
 HX_RESULT HXAVCDecoderConfigurationRecord::Unpack(BYTE* pBuf, UINT32 ulLen)
 {
     return UnpackInc(&pBuf, &ulLen);
@@ -96,11 +443,23 @@
                             retVal = UnpackUINT8Inc(ppBuf, pulLen, &m_ucNumSequenceParameterSets);
                             if (SUCCEEDED(retVal))
                             {
+                                BYTE i = 0;
                                 // The number of sequence parameter sets is only in the lower 5 bits
                                 // of this byte, so we need to mask out the upper 3 bits.
                                 m_ucNumSequenceParameterSets &= 0x1F;
+                                // Make sure we have at least one SPS
+                                if (m_ucNumSequenceParameterSets)
+                                {
+                                    // Set the return value
+                                    retVal = HXR_OUTOFMEMORY;
+                                    // Allocate an array of HXAVCSequenceParameterSet
+                                    HX_VECTOR_DELETE(m_pSPS);
+                                    m_pSPS = new HXAVCSequenceParameterSet [m_ucNumSequenceParameterSets];
+                                    if (m_pSPS)
+                                    {
+                                        // Clear the return value
+                                        retVal = HXR_OK;
                                 // Skip the sequence parameter sets
-                                BYTE i = 0;
                                 for (i = 0; i < m_ucNumSequenceParameterSets && SUCCEEDED(retVal); i++)
                                 {
                                     // Parse the size of the i-th sequence parameter set
@@ -108,18 +467,23 @@
                                     retVal = UnpackUINT16BEInc(ppBuf, pulLen, &usSize);
                                     if (SUCCEEDED(retVal))
                                     {
-                                        // Compute the number of bytes to skip
-                                        UINT32 ulBytesToSkip = usSize;
-                                        if (ulBytesToSkip > *pulLen)
-                                        {
-                                            ulBytesToSkip = *pulLen;
-                                            // The length of the i-th sequence parameter set is longer
-                                            // than the data provided, so fail.
+                                                // Set the return value
                                             retVal = HXR_FAIL;
+                                                // Make sure we have enough bytes to parse
+                                                UINT32 ulSize = usSize;
+                                                if (ulSize <= *pulLen)
+                                                {
+                                                    // Unpack the i-th SPS
+                                                    retVal = m_pSPS[i].Unpack(*ppBuf, ulSize);
+                                                    if (SUCCEEDED(retVal))
+                                                    {
+                                                        // Skip the i-th SPS
+                                                        *ppBuf  += ulSize;
+                                                        *pulLen -= ulSize;
+                                                    }
+                                                }
+                                            }
                                         }
-                                        // Skip the i-th sequence parameter set
-                                        *ppBuf  += ulBytesToSkip;
-                                        *pulLen -= ulBytesToSkip;
                                     }
                                 }
                                 if (SUCCEEDED(retVal))
@@ -128,6 +492,18 @@
                                     retVal = UnpackUINT8Inc(ppBuf, pulLen, &m_ucNumPictureParameterSets);
                                     if (SUCCEEDED(retVal))
                                     {
+                                        // Make sure we have at least one PPS
+                                        if (m_ucNumPictureParameterSets)
+                                        {
+                                            // Set the return value
+                                            retVal = HXR_OUTOFMEMORY;
+                                            // Allocate an array of PPS
+                                            HX_VECTOR_DELETE(m_pPPS);
+                                            m_pPPS = new HXAVCPictureParameterSet [m_ucNumPictureParameterSets];
+                                            if (m_pPPS)
+                                            {
+                                                // Clear the return value
+                                                retVal = HXR_OK;
                                         // Skip the picture parameter sets
                                         for (i = 0; i < m_ucNumPictureParameterSets && SUCCEEDED(retVal); i++)
                                         {
@@ -136,18 +512,23 @@
                                             retVal = UnpackUINT16BEInc(ppBuf, pulLen, &usSize);
                                             if (SUCCEEDED(retVal))
                                             {
-                                                // Compute the number of bytes to skip
-                                                UINT32 ulBytesToSkip = usSize;
-                                                if (ulBytesToSkip > *pulLen)
-                                                {
-                                                    ulBytesToSkip = *pulLen;
-                                                    // The length of the i-th picture parameter set is longer
-                                                    // than the data provided, so fail.
+                                                        // Set the return value
                                                     retVal = HXR_FAIL;
-                                                }
+                                                        // Make sure we have enough bytes to parse
+                                                        UINT32 ulSize = usSize;
+                                                        if (ulSize <= *pulLen)
+                                                        {
+                                                            // Parse the i-th PPS
+                                                            retVal = m_pPPS[i].Unpack(*ppBuf, ulSize);
+                                                            if (SUCCEEDED(retVal))
+                                                            {
                                                 // Skip the i-th sequence parameter set
-                                                *ppBuf  += ulBytesToSkip;
-                                                *pulLen -= ulBytesToSkip;
+                                                                *ppBuf  += ulSize;
+                                                                *pulLen -= ulSize;
+                                                            }
+                                                        }
+                                                    }
+                                                }
                                             }
                                         }
                                     }
@@ -163,6 +544,27 @@
     return retVal;
 }
 
+HX_RESULT HXAVCDecoderConfigurationRecord::GetLumaWidthHeight(UINT32* pulWidth, UINT32* pulHeight)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pulWidth && pulHeight)
+    {
+        // Set the return value
+        retVal = HXR_UNEXPECTED;
+        // Make sure we have at least one SPS
+        if (m_ucNumSequenceParameterSets && m_pSPS)
+        {
+            // We assume we only have one SPS
+            HX_ASSERT(m_ucNumSequenceParameterSets == 1);
+            // Get the width and height from the first SPS
+            retVal = m_pSPS[0].GetLumaWidthHeight(pulWidth, pulHeight);
+        }
+    }
+
+    return retVal;
+}
+
 HX_RESULT ParseNALUnitHeader(BYTE** ppBuf, UINT32* pulLen, UINT32* pulNALRefIDC, HXNALUnitType* peNALUnitType)
 {
     HX_RESULT retVal = HXR_INVALID_PARAMETER;
@@ -272,6 +674,105 @@
     return retVal;
 }
 
+HX_RESULT ParseBitstreamHXBOOL(Bitstream* pBS, HXBOOL* pbValue)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pBS && pbValue)
+    {
+        // Set the return value
+        retVal = HXR_FAIL;
+        // Make sure we have one bit
+        if (pBS->BitsLeft() >= 1)
+        {
+            // Get one bit from the bitstream
+            UINT32 ulTmp = pBS->GetBits(1);
+            // Set the out parameter
+            *pbValue = (ulTmp ? TRUE : FALSE);
+            // Clear the return value
+            retVal = HXR_OK;
+        }
+    }
+
+    return retVal;
+}
+
+HX_RESULT ParseScalingList(Bitstream* pBS, UINT32 ulIdx, BYTE* pucList, UINT32 ulListSize, HXBOOL* pbUseDefaultMatrix)
+{
+    HX_RESULT retVal = HXR_INVALID_PARAMETER;
+
+    if (pBS && pucList && ulListSize && pbUseDefaultMatrix)
+    {
+        // Clear the return value
+        retVal = HXR_OK;
+        // Parse ulListSize scales
+        INT32  lLastScale = 8;
+        INT32  lNextScale = 8;
+        UINT32 j          = 0;
+        for (j = 0; j < ulListSize && SUCCEEDED(retVal); j++)
+        {
+            if (lNextScale)
+            {
+                // Parse the delta_scale
+                INT32 lDeltaScale = 0;
+                retVal = ParseExpGolombSigned(pBS, &lDeltaScale);
+                if (SUCCEEDED(retVal))
+                {
+                    // Update nextScale
+                    lNextScale = (lLastScale + lDeltaScale + 256) % 256;
+                    // Set useDefaultScalingMatrixFlag
+                    *pbUseDefaultMatrix = ((j == 0 && lNextScale == 0) ? TRUE : FALSE);
+                }
+            }
+            if (SUCCEEDED(retVal))
+            {
+                pucList[j] = (BYTE) (lNextScale == 0 ? lLastScale : lNextScale);
+                lLastScale = pucList[j];
+            }
+        }
+        if (SUCCEEDED(retVal) && *pbUseDefaultMatrix)
+        {
+            // We are supposed to use the default scaling matrix for this index.
+            // Get the proper default matrix to use. This comes from Table 7-2
+            // in ITU-T Rec H.264.
+            const BYTE* pDefaultMatrix      = NULL;
+            UINT32      ulDefaultMatrixSize = 0;
+            if (ulIdx <= 2)
+            {
+                pDefaultMatrix      = g_ucDefault_4x4_Intra;
+                ulDefaultMatrixSize = 16;
+            }
+            else if (ulIdx >= 3 && ulIdx <= 5)
+            {
+                pDefaultMatrix      = g_ucDefault_4x4_Inter;
+                ulDefaultMatrixSize = 16;
+            }
+            else if (ulIdx >= 6 && ulIdx <= 8)
+            {
+                pDefaultMatrix      = g_ucDefault_8x8_Intra;
+                ulDefaultMatrixSize = 64;
+            }
+            else if (ulIdx >= 9 && ulIdx <= 11)
+            {
+                pDefaultMatrix      = g_ucDefault_8x8_Inter;
+                ulDefaultMatrixSize = 64;
+            }
+            // Set the return value
+            retVal = HXR_FAIL;
+            // Make sure the default matrix matches our matrix size
+            if (pDefaultMatrix && ulDefaultMatrixSize && ulDefaultMatrixSize == ulListSize)
+            {
+                // Copy the default matrix
+                memcpy(pucList, pDefaultMatrix, ulDefaultMatrixSize * sizeof(BYTE));
+                // Clear the return value
+                retVal = HXR_OK;
+            }
+        }
+    }
+
+    return retVal;
+}
+
 HX_RESULT ParseSliceHeader(BYTE* pBuf, UINT32 ulLen, UINT32* pulFirstMBInSlice,
                            HXSliceType* peSliceType, UINT32* pulPictureParameterSetID)
 {
Index: pub/hx_parse_h264.h
===================================================================
RCS file: /cvsroot/datatype/h264/common/pub/hx_parse_h264.h,v
retrieving revision 1.1
diff -u -w -u -w -r1.1 hx_parse_h264.h
--- pub\hx_parse_h264.h	20 May 2009 13:25:02 -0000	1.1
+++ pub\hx_parse_h264.h	25 Jun 2009 19:42:55 -0000
@@ -109,6 +109,182 @@
     HXNumSliceTypes
 };
 
+class HXAVCSequenceParameterSet
+{
+public:
+    HXAVCSequenceParameterSet()
+        : m_ucProfileIDC(0)
+        , m_bConstraintSet0Flag(FALSE)
+        , m_bConstraintSet1Flag(FALSE)
+        , m_bConstraintSet2Flag(FALSE)
+        , m_bConstraintSet3Flag(FALSE)
+        , m_ucLevelIDC(0)
+        , m_ulSeqParameterSetID(0)
+        , m_ulChromaFormatIDC(0)
+        , m_bSeparateColourPlaneFlag(FALSE)
+        , m_ulBitDepthLumaMinus8(0)
+        , m_ulBitDepthChromaMinus8(0)
+        , m_bQPPrimeYZeroTransformBypassFlag(FALSE)
+        , m_bSeqScalingMatrixPresentFlag(FALSE)
+        , m_ulLog2MaxFrameNumMinus4(0)
+        , m_ulPicOrderCntType(0)
+        , m_ulLog2MaxPicOrderCntLsbMinus4(0)
+        , m_bDeltaPicOrderAlwaysZeroFlag(FALSE)
+        , m_lOffsetForNonRefPic(0)
+        , m_lOffsetForTopToBottomField(0)
+        , m_ulNumRefFramesInPicOrderCntCycle(0)
+        , m_plOffsetForRefFrame(NULL)
+        , m_ulNumRefFrames(0)
+        , m_bGapsInFrameNumValueAllowedFlag(FALSE)
+        , m_ulPicWidthInMbsMinus1(0)
+        , m_ulPicHeightInMapUnitsMinus1(0)
+        , m_bFrameMbsOnlyFlag(FALSE)
+        , m_bMbAdaptiveFrameFieldFlag(FALSE)
+        , m_bDirect8x8InferenceFlag(FALSE)
+        , m_bFrameCroppingFlag(FALSE)
+        , m_ulFrameCropLeftOffset(0)
+        , m_ulFrameCropRightOffset(0)
+        , m_ulFrameCropTopOffset(0)
+        , m_ulFrameCropBottomOffset(0)
+        , m_bVuiParametersPresentFlag(FALSE)
+    {
+        memset(m_bSeqScalingListPresent, 0, 12 * sizeof(HXBOOL));
+        memset(m_ucScalingList4x4, 0, 6 * 16 * sizeof(BYTE));
+        memset(m_ucScalingList8x8, 0, 6 * 64 * sizeof(BYTE));
+        memset(m_bUseDefaultScalingMatrix4x4Flag, 0, 6 * sizeof(HXBOOL));
+        memset(m_bUseDefaultScalingMatrix8x8Flag, 0, 6 * sizeof(HXBOOL));
+    };
+
+    ~HXAVCSequenceParameterSet()
+    {
+        HX_VECTOR_DELETE(m_plOffsetForRefFrame);
+    };
+
+    HX_RESULT Unpack(BYTE* pBuf, UINT32 ulLen);
+    HX_RESULT GetLumaWidthHeight(UINT32* pulWidth, UINT32* pulHeight);
+private:
+    BYTE        m_ucProfileIDC;
+    HXBOOL      m_bConstraintSet0Flag;
+    HXBOOL      m_bConstraintSet1Flag;
+    HXBOOL      m_bConstraintSet2Flag;
+    HXBOOL      m_bConstraintSet3Flag;
+    BYTE        m_ucLevelIDC;
+    UINT32      m_ulSeqParameterSetID;
+    UINT32      m_ulChromaFormatIDC;
+    HXBOOL      m_bSeparateColourPlaneFlag;
+    UINT32      m_ulBitDepthLumaMinus8;
+    UINT32      m_ulBitDepthChromaMinus8;
+    HXBOOL      m_bQPPrimeYZeroTransformBypassFlag;
+    HXBOOL      m_bSeqScalingMatrixPresentFlag;
+    HXBOOL      m_bSeqScalingListPresent[12];
+    BYTE        m_ucScalingList4x4[6][16];
+    BYTE        m_ucScalingList8x8[6][64];
+    HXBOOL      m_bUseDefaultScalingMatrix4x4Flag[6];
+    HXBOOL      m_bUseDefaultScalingMatrix8x8Flag[6];
+    UINT32      m_ulLog2MaxFrameNumMinus4;
+    UINT32      m_ulPicOrderCntType;
+    UINT32      m_ulLog2MaxPicOrderCntLsbMinus4;
+    HXBOOL      m_bDeltaPicOrderAlwaysZeroFlag;
+    INT32       m_lOffsetForNonRefPic;
+    INT32       m_lOffsetForTopToBottomField;
+    UINT32      m_ulNumRefFramesInPicOrderCntCycle;
+    INT32*      m_plOffsetForRefFrame;
+    UINT32      m_ulNumRefFrames;
+    HXBOOL      m_bGapsInFrameNumValueAllowedFlag;
+    UINT32      m_ulPicWidthInMbsMinus1;
+    UINT32      m_ulPicHeightInMapUnitsMinus1;
+    HXBOOL      m_bFrameMbsOnlyFlag;
+    HXBOOL      m_bMbAdaptiveFrameFieldFlag;
+    HXBOOL      m_bDirect8x8InferenceFlag;
+    HXBOOL      m_bFrameCroppingFlag;
+    UINT32      m_ulFrameCropLeftOffset;
+    UINT32      m_ulFrameCropRightOffset;
+    UINT32      m_ulFrameCropTopOffset;
+    UINT32      m_ulFrameCropBottomOffset;
+    HXBOOL      m_bVuiParametersPresentFlag;
+};
+
+class HXAVCPictureParameterSet
+{
+public:
+    HXAVCPictureParameterSet()
+        : m_ulPicParameterSetID(0)
+        , m_ulSeqParameterSetID(0)
+        , m_bEntropyCodingModeFlag(FALSE)
+        , m_bPicOrderPresentFlag(FALSE)
+        , m_ulNumSliceGroupsMinus1(0)
+        , m_ulSliceGroupMapType(0)
+        , m_pulRunLengthMinus1(NULL)
+        , m_pulTopLeft(NULL)
+        , m_pulBottomRight(NULL)
+        , m_bSliceGroupChangeDirectionFlag(FALSE)
+        , m_ulSliceGroupChangeRateMinus1(0)
+        , m_ulPicSizeInMapUnitsMinus1(0)
+        , m_pulSlideGroupID(NULL)
+        , m_ulNumRefIdx10ActiveMinus1(0)
+        , m_ulNumRefIdx11ActiveMinus1(0)
+        , m_bWeightedPredFlag(FALSE)
+        , m_ucWeightedBipredIDC(0)
+        , m_lPicInitQpMinus26(0)
+        , m_lPicInitQsMinus26(0)
+        , m_lChromaQpIndexOffset(0)
+        , m_bDeblockingFilterControlPresentFlag(FALSE)
+        , m_bConstrainedIntraPredFlag(FALSE)
+        , m_bRedundantPicCntPresentFlag(FALSE)
+        , m_bTransform8x8ModeFlag(FALSE)
+        , m_bPixScalingMatrixPresentFlag(FALSE)
+        , m_lSecondChromaQpIndexOffset(0)
+    {
+        memset(m_bPicScalingListPresentFlag, 0, 12 * sizeof(HXBOOL));
+        memset(m_ucScalingList4x4, 0, 6 * 16 * sizeof(BYTE));
+        memset(m_ucScalingList8x8, 0, 6 * 64 * sizeof(BYTE));
+        memset(m_bUseDefaultScalingMatrix4x4Flag, 0, 6 * sizeof(HXBOOL));
+        memset(m_bUseDefaultScalingMatrix8x8Flag, 0, 6 * sizeof(HXBOOL));
+    };
+
+    ~HXAVCPictureParameterSet()
+    {
+        HX_VECTOR_DELETE(m_pulRunLengthMinus1);
+        HX_VECTOR_DELETE(m_pulTopLeft);
+        HX_VECTOR_DELETE(m_pulBottomRight);
+        HX_VECTOR_DELETE(m_pulSlideGroupID);
+    };
+
+    HX_RESULT Unpack(BYTE* pBuf, UINT32 ulLen);
+private:
+    UINT32  m_ulPicParameterSetID;
+    UINT32  m_ulSeqParameterSetID;
+    HXBOOL  m_bEntropyCodingModeFlag;
+    HXBOOL  m_bPicOrderPresentFlag;
+    UINT32  m_ulNumSliceGroupsMinus1;
+    UINT32  m_ulSliceGroupMapType;
+    UINT32* m_pulRunLengthMinus1;
+    UINT32* m_pulTopLeft;
+    UINT32* m_pulBottomRight;
+    HXBOOL  m_bSliceGroupChangeDirectionFlag;
+    UINT32  m_ulSliceGroupChangeRateMinus1;
+    UINT32  m_ulPicSizeInMapUnitsMinus1;
+    UINT32* m_pulSlideGroupID;
+    UINT32  m_ulNumRefIdx10ActiveMinus1;
+    UINT32  m_ulNumRefIdx11ActiveMinus1;
+    HXBOOL  m_bWeightedPredFlag;
+    BYTE    m_ucWeightedBipredIDC;
+    INT32   m_lPicInitQpMinus26;
+    INT32   m_lPicInitQsMinus26;
+    INT32   m_lChromaQpIndexOffset;
+    HXBOOL  m_bDeblockingFilterControlPresentFlag;
+    HXBOOL  m_bConstrainedIntraPredFlag;
+    HXBOOL  m_bRedundantPicCntPresentFlag;
+    HXBOOL  m_bTransform8x8ModeFlag;
+    HXBOOL  m_bPixScalingMatrixPresentFlag;
+    HXBOOL  m_bPicScalingListPresentFlag[12];
+    BYTE    m_ucScalingList4x4[6][16];
+    BYTE    m_ucScalingList8x8[6][64];
+    HXBOOL  m_bUseDefaultScalingMatrix4x4Flag[6];
+    HXBOOL  m_bUseDefaultScalingMatrix8x8Flag[6];
+    INT32   m_lSecondChromaQpIndexOffset;
+};
+
 class HXAVCDecoderConfigurationRecord
 {
 public:
@@ -120,11 +296,15 @@
         , m_ucNumBytesInNALUnitLength(0)
         , m_ucNumSequenceParameterSets(0)
         , m_ucNumPictureParameterSets(0)
+        , m_pSPS(NULL)
+        , m_pPPS(NULL)
     {
     };
 
     ~HXAVCDecoderConfigurationRecord()
     {
+        HX_VECTOR_DELETE(m_pSPS);
+        HX_VECTOR_DELETE(m_pPPS);
     };
 
     HX_RESULT Unpack(BYTE* pBuf, UINT32 ulLen);
@@ -137,6 +317,7 @@
     BYTE GetNumBytesInNALUnitLength()  const { return m_ucNumBytesInNALUnitLength;  }
     BYTE GetNumSequenceParameterSets() const { return m_ucNumSequenceParameterSets; }
     BYTE GetNumPictureParameterSets()  const { return m_ucNumPictureParameterSets;  }
+    HX_RESULT GetLumaWidthHeight(UINT32* pulWidth, UINT32* pulHeight);
 private:
     BYTE m_ucConfigurationVersion;
     BYTE m_ucAVCProfileIndication;
@@ -145,12 +326,16 @@
     BYTE m_ucNumBytesInNALUnitLength;
     BYTE m_ucNumSequenceParameterSets;
     BYTE m_ucNumPictureParameterSets;
+    HXAVCSequenceParameterSet* m_pSPS;
+    HXAVCPictureParameterSet*  m_pPPS;
 };
 
 HX_RESULT ParseNALUnitHeader(BYTE** ppBuf, UINT32* pulLen, UINT32* pulNALRefIDC, HXNALUnitType* peNALUnitType);
 HX_RESULT ParseExpGolombCode(Bitstream* pBS, UINT32* pulCodeNum);
 HX_RESULT ParseExpGolombUnsigned(Bitstream* pBS, UINT32* pulValue);
 HX_RESULT ParseExpGolombSigned(Bitstream* pBS, INT32* plValue);
+HX_RESULT ParseBitstreamHXBOOL(Bitstream* pBS, HXBOOL* pbValue);
+HX_RESULT ParseScalingList(Bitstream* pBS, UINT32 ulIdx, BYTE* pucList, UINT32 ulListSize, HXBOOL* pbUseDefaultMatrix);
 HX_RESULT ParseSliceHeader(BYTE* pBuf, UINT32 ulLen, UINT32* pulFirstMBInSlice,
                            HXSliceType* peSliceType, UINT32* pulPictureParameterSetID);
 // This method parses one or more NAL Units, including the 1/2/4 byte NAL unit length.


More information about the Datatype-dev mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.