shithub: openh264

Download patch

ref: 4ebaba864c1e8b4ef399860857dc29ca1c121a9a
parent: 5b5134eaeabb6620c68310a78cadcb7a8d473bce
author: huili2 <huili2@cisco.com>
date: Mon Nov 14 09:31:37 EST 2016

add part of VUI parse in sps, and add SAR option in GetOption()

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -160,7 +160,8 @@
   DECODER_OPTION_TRACE_CALLBACK,        ///< a void (*)(void* context, int level, const char* message) function which receives log messages
   DECODER_OPTION_TRACE_CALLBACK_CONTEXT,///< context info of trace callbac
 
-  DECODER_OPTION_GET_STATISTICS
+  DECODER_OPTION_GET_STATISTICS,        ///< feedback decoder statistics
+  DECODER_OPTION_GET_SAR_INFO,          ///< feedback decoder Sample Aspect Ratio info in Vui
 
 } DECODER_OPTION;
 
@@ -670,7 +671,7 @@
 } SDecoderCapability;
 
 /**
-* @brief to do
+* @brief Structure for parse only output
 */
 typedef struct TagParserBsInfo {
   int iNalNum;                                 ///< total NAL number in current AU
@@ -737,5 +738,14 @@
   int iSubSpsNoExistNalNum;                    ///< number of SubSps NoExist Nal
   int iPpsNoExistNalNum;                       ///< number of Pps NoExist Nal
 } SDecoderStatistics; // in building, coming soon
+
+/**
+* @brief Structure for sample aspect ratio (SAR) info in VUI
+*/
+typedef struct TagVuiSarInfo {
+  unsigned int uiSarWidth;                     ///< SAR width
+  unsigned int uiSarHeight;                    ///< SAR height
+  bool bOverscanAppropriateFlag;               ///< SAR overscan flag
+} SVuiSarInfo, *PVuiSarInfo;
 
 #endif//WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
--- a/codec/common/inc/wels_common_defs.h
+++ b/codec/common/inc/wels_common_defs.h
@@ -214,6 +214,17 @@
   MMCO_LONG         = 6
 };
 
+enum EVuiVideoFormat {
+   VUI_COMPONENT   = 0,
+   VUI_PAL         = 1,
+   VUI_NTSC        = 2,
+   VUI_SECAM       = 3,
+   VUI_MAC         = 4,
+   VUI_UNSPECIFIED = 5,
+   VUI_RESERVED1   = 6,
+   VUI_RESERVED2   = 7
+};
+
 /*
  *  Bit-stream auxiliary reading / writing
  */
--- a/codec/decoder/core/inc/au_parser.h
+++ b/codec/decoder/core/inc/au_parser.h
@@ -132,6 +132,22 @@
 int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal, const int32_t kSrcNalLen);
 
 /*!
+*************************************************************************************
+* \brief   to parse Video Usability Information (VUI) parameter of the SPS
+*
+* \param   pCtx        Decoder context
+* \param   pSps        the sps which current Vui parameter belongs to
+* \param   pBsAux      bitstream reader auxiliary
+*
+* \return  0 - successed
+*          1 - failed
+*
+* \note    Call it in case the flag "vui_parameters_present_flag" in sps is true.
+*************************************************************************************
+*/
+int32_t ParseVui(PWelsDecoderContext pCtx, PSps pSps, PBitStringAux pBsAux);
+
+/*!
  *************************************************************************************
  * \brief to parse scaling list message payload
  *
--- a/codec/decoder/core/inc/dec_golomb.h
+++ b/codec/decoder/core/inc/dec_golomb.h
@@ -336,6 +336,10 @@
 
 // From Level 5.2
 #define MAX_MB_SIZE 36864
+// for aspect_ratio_idc
+#define EXTENDED_SAR 255
+// for chroma_sample_loc_type_top_field & chroma_sample_loc_type_bottom_field
+#define VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD 5
 } // namespace WelsDec
 
 #endif//WELS_EXPONENTIAL_GOLOMB_ENTROPY_CODING_H__
--- a/codec/decoder/core/inc/parameter_sets.h
+++ b/codec/decoder/core/inc/parameter_sets.h
@@ -38,8 +38,31 @@
 #include "wels_common_basis.h"
 
 namespace WelsDec {
+  /* VUI syntax in Sequence Parameter Set, refer to E.1 in Rec */
+  typedef struct TagVui {
+    bool bAspectRatioInfoPresentFlag;
+    uint32_t uiAspectRatioIdc;
+    uint32_t uiSarWidth;
+    uint32_t uiSarHeight;
+    bool bOverscanInfoPresentFlag;
+    bool bOverscanAppropriateFlag;
+    bool bVideoSignalTypePresentFlag;
+    uint8_t uiVideoFormat;
+    bool bVideoFullRangeFlag;
+    bool bColourDescripPresentFlag;
+    uint8_t uiColourPrimaries;
+    uint8_t uiTransferCharacteristics;
+    uint8_t uiMatrixCoeffs;
+    bool bChromaLocInfoPresentFlag;
+    uint32_t uiChromaSampleLocTypeTopField;
+    uint32_t uiChromaSampleLocTypeBottomField;
+    bool bTimingInfoPresentFlag;
+    uint32_t uiNumUnitsInTick;
+    uint32_t uiTimeScale;
+    bool bFixedFrameRateFlag;
+    bool bNalHrdParamPresentFlag;
+  } SVui, *PVui;
 
-
 /* Sequence Parameter Set, refer to Page 57 in JVT X201wcm */
 typedef struct TagSps {
   int32_t       iSpsId;
@@ -91,7 +114,7 @@
   //Add scaling list supporting
   uint8_t  iScalingList4x4[6][16];
   uint8_t  iScalingList8x8[6][64];
-
+  SVui sVui;
 const SLevelLimits* pSLevelLimits;
 } SSps, *PSps;
 
--- a/codec/decoder/core/inc/wels_common_basis.h
+++ b/codec/decoder/core/inc/wels_common_basis.h
@@ -251,6 +251,18 @@
     {SUB_MB_TYPE_4x4, 4, 1},
 };
 
+typedef struct TagSar {
+  uint32_t uiWidth;
+  uint32_t uiHeight;
+} sSar;
+static const sSar g_ksVuiSampleAspectRatio[17] = { //Table E-1
+  { 0,  0}, { 1,  1}, {12, 11}, { 10, 11}, {16,11}, //0~4
+  {40, 33}, {24, 11}, {20, 11}, { 32, 11}, {80,33}, //5~9
+  {18, 11}, {15, 11}, {64, 33}, {160, 99}, { 4, 3}, //10~14
+  { 3,  2}, { 2,  1}                                //15~16
+};
+
+
 } // namespace WelsDec
 
 #endif//WELS_COMMON_BASIS_H__
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -1134,7 +1134,9 @@
   }
   WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //vui_parameters_present_flag
   pSps->bVuiParamPresentFlag = !!uiCode;
-
+  if (pSps->bVuiParamPresentFlag && !kbUseSubsetFlag) { //parse Part of Vui Parameters in avc sps only
+    WELS_READ_VERIFY (ParseVui (pCtx, pSps, pBsAux));
+  }
   if (pCtx->pParam->bParseOnly) {
     if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //sps bs exceeds!
       pCtx->iErrorCode |= dsOutOfMemory;
@@ -1425,9 +1427,10 @@
     if (memcmp (pCtx->pPps, pPps, sizeof (*pPps)) != 0) {
       memcpy (&pCtx->sPpsBuffer[MAX_PPS_COUNT], pPps, sizeof (SPps));
       pCtx->iOverwriteFlags |= OVERWRITE_PPS;
-      pCtx->bAuReadyFlag = true;
-      pCtx->pAccessUnitList->uiEndPos = (pCtx->pAccessUnitList->uiAvailUnitsNum > 0 ? (pCtx->pAccessUnitList->uiAvailUnitsNum
-                                         - 1) : 0);
+      if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
+        pCtx->bAuReadyFlag = true;
+        pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
+      }
     }
   } else {
     memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
@@ -1456,7 +1459,75 @@
   }
   return ERR_NONE;
 }
+int32_t ParseVui (PWelsDecoderContext pCtx, PSps pSps, PBitStringAux pBsAux) {
+  uint32_t uiCode;
+  PVui pVui = &pSps->sVui;
+  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //aspect_ratio_info_present_flag
+  pVui->bAspectRatioInfoPresentFlag = !!uiCode;
+  if (pSps->sVui.bAspectRatioInfoPresentFlag) {
+    WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); //aspect_ratio_idc
+    pVui->uiAspectRatioIdc = uiCode;
+    if (pVui->uiAspectRatioIdc < 17) {
+      pVui->uiSarWidth  = g_ksVuiSampleAspectRatio[pVui->uiAspectRatioIdc].uiWidth;
+      pVui->uiSarHeight = g_ksVuiSampleAspectRatio[pVui->uiAspectRatioIdc].uiHeight;
+    } else if (pVui->uiAspectRatioIdc == EXTENDED_SAR) {
+      WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); //sar_width
+      pVui->uiSarWidth = uiCode;
+      WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); //sar_height
+      pVui->uiSarHeight = uiCode;
+    }
+  }
+  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //overscan_info_present_flag
+  pVui->bOverscanInfoPresentFlag = !!uiCode;
+  if (pVui->bOverscanInfoPresentFlag) {
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //overscan_appropriate_flag
+    pVui->bOverscanAppropriateFlag = !!uiCode;
+  }
+  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //video_signal_type_present_flag
+  pVui->bVideoSignalTypePresentFlag = !!uiCode;
+  if (pVui->bVideoSignalTypePresentFlag) {
+    WELS_READ_VERIFY (BsGetBits (pBsAux, 3, &uiCode)); //video_format
+    pVui->uiVideoFormat = uiCode;
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //video_full_range_flag
+    pVui->bVideoFullRangeFlag = !!uiCode;
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //colour_description_present_flag
+    pVui->bColourDescripPresentFlag = !!uiCode;
+    if (pVui->bColourDescripPresentFlag) {
+      WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); //colour_primaries
+      pVui->uiColourPrimaries = uiCode;
+      WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); //transfer_characteristics
+      pVui->uiTransferCharacteristics = uiCode;
+      WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); //matrix_coefficients
+      pVui->uiMatrixCoeffs = uiCode;
+    }
+  }
+  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //chroma_loc_info_present_flag
+  pVui->bChromaLocInfoPresentFlag = !!uiCode;
+  if (pVui->bChromaLocInfoPresentFlag) {
+    WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); //chroma_sample_loc_type_top_field
+    pVui->uiChromaSampleLocTypeTopField = uiCode;
+    WELS_CHECK_SE_UPPER_WARNING (pVui->uiChromaSampleLocTypeTopField, VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD,
+                                 "chroma_sample_loc_type_top_field");
+    WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); //chroma_sample_loc_type_bottom_field
+    pVui->uiChromaSampleLocTypeBottomField = uiCode;
+    WELS_CHECK_SE_UPPER_WARNING (pVui->uiChromaSampleLocTypeBottomField, VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD,
+                                 "chroma_sample_loc_type_bottom_field");
+  }
+  WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //timing_info_present_flag
+  pVui->bTimingInfoPresentFlag = !!uiCode;
+  if (pVui->bTimingInfoPresentFlag) {
+    WELS_READ_VERIFY (BsGetBits (pBsAux, 32, &uiCode)); //num_units_in_tick
+    pVui->uiNumUnitsInTick = uiCode;
+    WELS_CHECK_SE_LOWER_WARNING (pVui->uiNumUnitsInTick, 1, "num_units_in_tick");
+    WELS_READ_VERIFY (BsGetBits (pBsAux, 32, &uiCode)); //time_scale
+    pVui->uiTimeScale = uiCode;
+    WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); //fixed_frame_rate_flag
+    pVui->bFixedFrameRateFlag = !!uiCode;
+  }
+  //following HRD related parameters, omitted
 
+  return ERR_NONE;
+}
 /*!
  *************************************************************************************
  * \brief   to parse SEI message payload
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -345,9 +345,11 @@
     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
              "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
     return cmInitParaError;
+  } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
+             "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
+    return cmInitParaError;
   }
-
-
   return cmInitParaError;
 }
 
@@ -412,6 +414,17 @@
            m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
     }
     return cmResultSuccess;
+  } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
+    PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
+    memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
+    if (!m_pDecContext->pSps) {
+      return cmInitExpected;
+    } else {
+      pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth;
+      pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight;
+      pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag;
+      return cmResultSuccess;
+    }
   }
 
   return cmInitParaError;
binary files /dev/null b/res/SarVui.264 differ
--- a/test/decoder/DecUT_DecExt.cpp
+++ b/test/decoder/DecUT_DecExt.cpp
@@ -63,6 +63,8 @@
   void TestTraceCallbackContext();
   //DECODER_OPTION_GET_DECODER_STATICTIS
   void TestGetDecStatistics();
+  //DECODER_OPTION_GET_SAR_INFO
+  void TestGetDecSarInfo();
   //Do whole tests here
   void DecoderInterfaceAll();
 
@@ -607,6 +609,33 @@
   Uninit();
 
 }
+
+//DECODER_OPTION_GET_SAR_INFO
+void DecoderInterfaceTest::TestGetDecSarInfo() {
+  CM_RETURN eRet;
+  int32_t iRet;
+  SVuiSarInfo sVuiSarInfo;
+
+  iRet = ValidInit();
+  ASSERT_EQ (iRet, ERR_NONE);
+  //GetOption before decoding
+  m_pDec->GetOption (DECODER_OPTION_GET_SAR_INFO, &sVuiSarInfo);
+  EXPECT_EQ (0u, sVuiSarInfo.uiSarWidth);
+  EXPECT_EQ (0u, sVuiSarInfo.uiSarHeight);
+  EXPECT_EQ (0u, sVuiSarInfo.bOverscanAppropriateFlag);
+  // setoption not support,
+  eRet = (CM_RETURN)m_pDec->SetOption (DECODER_OPTION_GET_SAR_INFO, NULL);
+  EXPECT_EQ (eRet, cmInitParaError);
+
+  //Decoder specific bs
+  DecoderBs ("res/SarVui.264");
+  m_pDec->GetOption (DECODER_OPTION_GET_SAR_INFO, &sVuiSarInfo);
+  EXPECT_EQ (80u, sVuiSarInfo.uiSarWidth);  //DO NOT MODIFY the data value
+  EXPECT_EQ (33u, sVuiSarInfo.uiSarHeight); //DO NOT MODIFY the data value
+  EXPECT_EQ (1u, sVuiSarInfo.bOverscanAppropriateFlag); //DO NOT MODIFY the data value
+  Uninit();
+}
+
 //TEST here for whole tests
 TEST_F (DecoderInterfaceTest, DecoderInterfaceAll) {
 
@@ -636,6 +665,8 @@
   TestTraceCallbackContext();
   //DECODER_OPTION_GET_STATISTICS
   TestGetDecStatistics();
+  //DECODER_OPTION_GET_SAR_INFO
+  TestGetDecSarInfo();
 }
 
 
--- a/test/decoder/DecUT_ParseSyntax.cpp
+++ b/test/decoder/DecUT_ParseSyntax.cpp
@@ -164,7 +164,7 @@
   m_sDecParam.uiTargetDqLayer = rand() % 100;
   m_sDecParam.eEcActiveIdc = (ERROR_CON_IDC)7;
   m_sDecParam.sVideoProperty.size = sizeof (SVideoProperty);
-  m_sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE) (rand() % 3);
+  m_sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE) (rand() % 2);
   m_sDecParam.bParseOnly = false;
 
   m_pData[0] = m_pData[1] = m_pData[2] = NULL;