shithub: openh264

Download patch

ref: 027f027c25c194e790f3b0ad9914bfce8f56d492
parent: 3e538617cdead5397f61af82dbb7b6eaafdff62c
parent: 03890fe86f4841264c5b83076de10fd4dde36fc7
author: HaiboZhu <haibozhu@cisco.com>
date: Thu Feb 25 05:49:34 EST 2016

Merge pull request #2371 from GregoryJWolfe/master

Added support for "video signal type present" information.

--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,4 +1,4 @@
-# Contributors to the OpenH264 project
+# Contributors to the OpenH264 project
 
 Patrick Ai
 Sijia Chen
@@ -35,6 +35,7 @@
 Juanny Wang
 Zhiliang Wang
 Hervé Willems
+Gregory J Wolfe
 Katherine Wu
 Guang Xu
 Jeffery Xu
--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -344,6 +344,77 @@
 } SSliceArgument;
 
 /**
+* @brief Enumerate the type of video format
+*/
+typedef enum {
+  VF_COMPONENT,
+  VF_PAL,
+  VF_NTSC,
+  VF_SECAM,
+  VF_MAC,
+  VF_UNDEF,
+  VF_NUM_ENUM
+} EVideoFormatSPS;	// EVideoFormat is already defined/used elsewhere!
+
+/**
+* @brief Enumerate the type of color primaries
+*/
+typedef enum {
+  CP_RESERVED0,
+  CP_BT709,
+  CP_UNDEF,
+  CP_RESERVED3,
+  CP_BT470M,
+  CP_BT470BG,
+  CP_SMPTE170M,
+  CP_SMPTE240M,
+  CP_FILM,
+  CP_BT2020,
+  CP_NUM_ENUM
+} EColorPrimaries;
+
+/**
+* @brief Enumerate the type of transfer characteristics
+*/
+typedef enum {
+  TRC_RESERVED0,
+  TRC_BT709,
+  TRC_UNDEF,
+  TRC_RESERVED3,
+  TRC_BT470M,
+  TRC_BT470BG,
+  TRC_SMPTE170M,
+  TRC_SMPTE240M,
+  TRC_LINEAR,
+  TRC_LOG100,
+  TRC_LOG316,
+  TRC_IEC61966_2_4,
+  TRC_BT1361E,
+  TRC_IEC61966_2_1,
+  TRC_BT2020_10,
+  TRC_BT2020_12,
+  TRC_NUM_ENUM
+} ETransferCharacteristics;
+
+/**
+* @brief Enumerate the type of color matrix
+*/
+typedef enum {
+  CM_GBR,
+  CM_BT709,
+  CM_UNDEF,
+  CM_RESERVED3,
+  CM_FCC,
+  CM_BT470BG,
+  CM_SMPTE170M,
+  CM_SMPTE240M,
+  CM_YCGCO,
+  CM_BT2020NC,
+  CM_BT2020C,
+  CM_NUM_ENUM
+} EColorMatrix;
+
+/**
 * @brief  Structure for spatial layer configuration
 */
 typedef struct {
@@ -357,6 +428,18 @@
   int          iDLayerQp;      ///< value of level IDC (0 for auto-detection)
 
   SSliceArgument sSliceArgument;
+
+  // Note: members bVideoSignalTypePresent through uiColorMatrix below are also defined in SWelsSPS in parameter_sets.h.
+  bool			bVideoSignalTypePresent;	// false => do not write any of the following information to the header
+  unsigned char	uiVideoFormat;				// EVideoFormatSPS; 3 bits in header; 0-5 => component, kpal, ntsc, secam, mac, undef
+  bool			bFullRange;					// false => analog video data range [16, 235]; true => full data range [0,255]
+  bool			bColorDescriptionPresent;	// false => do not write any of the following three items to the header
+  unsigned char	uiColorPrimaries;			// EColorPrimaries; 8 bits in header; 0 - 9 => ???, bt709, undef, ???, bt470m, bt470bg,
+                                            //    smpte170m, smpte240m, film, bt2020
+  unsigned char	uiTransferCharacteristics;	// ETransferCharacteristics; 8 bits in header; 0 - 15 => ???, bt709, undef, ???, bt470m, bt470bg, smpte170m,
+										    //   smpte240m, linear, log100, log316, iec61966-2-4, bt1361e, iec61966-2-1, bt2020-10, bt2020-12
+  unsigned char	uiColorMatrix;				// EColorMatrix; 8 bits in header (corresponds to FFmpeg "colorspace"); 0 - 10 => GBR, bt709,
+										    //   undef, ???, fcc, bt470bg, smpte170m, smpte240m, YCgCo, bt2020nc, bt2020c
 } SSpatialLayerConfig;
 
 /**
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -190,6 +190,16 @@
       const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
       for (int32_t idx = 0; idx < kiLesserSliceNum; idx++)
         param.sSpatialLayers[iLayer].sSliceArgument.uiSliceMbNum[idx] = 0; //default, using one row a slice if uiSliceMode is SM_RASTER_MODE
+
+      // See codec_app_def.h for more info about members bVideoSignalTypePresent through uiColorMatrix.  The default values
+      // used below preserve the previous behavior; i.e., no additional information will be written to the output file.
+      param.sSpatialLayers[iLayer].bVideoSignalTypePresent = false;			// do not write any of the following information to the header
+      param.sSpatialLayers[iLayer].uiVideoFormat = VF_UNDEF;				// undefined
+      param.sSpatialLayers[iLayer].bFullRange = false;						// analog video data range [16, 235]
+      param.sSpatialLayers[iLayer].bColorDescriptionPresent = false;		// do not write any of the following three items to the header
+      param.sSpatialLayers[iLayer].uiColorPrimaries = CP_UNDEF;				// undefined
+      param.sSpatialLayers[iLayer].uiTransferCharacteristics = TRC_UNDEF;	// undefined
+      param.sSpatialLayers[iLayer].uiColorMatrix = CM_UNDEF;				// undefined
     }
   }
 
@@ -407,6 +417,15 @@
               sizeof (SSliceArgument)) ;
 
       pSpatialLayer->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp;
+
+      // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
+      pSpatialLayer->bVideoSignalTypePresent =   pCodingParam.sSpatialLayers[iIdxSpatial].bVideoSignalTypePresent;
+      pSpatialLayer->uiVideoFormat =             pCodingParam.sSpatialLayers[iIdxSpatial].uiVideoFormat;
+      pSpatialLayer->bFullRange =                pCodingParam.sSpatialLayers[iIdxSpatial].bFullRange;
+      pSpatialLayer->bColorDescriptionPresent =  pCodingParam.sSpatialLayers[iIdxSpatial].bColorDescriptionPresent;
+      pSpatialLayer->uiColorPrimaries =          pCodingParam.sSpatialLayers[iIdxSpatial].uiColorPrimaries;
+      pSpatialLayer->uiTransferCharacteristics = pCodingParam.sSpatialLayers[iIdxSpatial].uiTransferCharacteristics;
+      pSpatialLayer->uiColorMatrix =             pCodingParam.sSpatialLayers[iIdxSpatial].uiColorMatrix;
 
       uiProfileIdc = (!bSimulcastAVC) ? PRO_SCALABLE_BASELINE : PRO_BASELINE;
       ++ pDlp;
--- a/codec/encoder/core/inc/parameter_sets.h
+++ b/codec/encoder/core/inc/parameter_sets.h
@@ -79,6 +79,19 @@
 // bool            bTimingInfoPresentFlag;
 // bool            bFixedFrameRateFlag;
 
+// Note: members bVideoSignalTypePresent through uiColorMatrix below are also defined in SSpatialLayerConfig in codec_app_def.h,
+// along with definitions for enumerators EVideoFormatSPS, EColorPrimaries, ETransferCharacteristics, and EColorMatrix.
+bool	bVideoSignalTypePresent;	// false => do not write any of the following information to the header
+uint8_t	uiVideoFormat;				// EVideoFormatSPS; 3 bits in header; 0-5 => component, kpal, ntsc, secam, mac, undef
+bool	bFullRange;					// false => analog video data range [16, 235]; true => full data range [0,255]
+bool	bColorDescriptionPresent;	// false => do not write any of the following three items to the header
+uint8_t	uiColorPrimaries;			// EColorPrimaries; 8 bits in header; 0 - 9 => ???, bt709, undef, ???, bt470m, bt470bg,
+                                    //    smpte170m, smpte240m, film, bt2020
+uint8_t	uiTransferCharacteristics;	// ETransferCharacteristics; 8 bits in header; 0 - 15 => ???, bt709, undef, ???, bt470m, bt470bg, smpte170m,
+                                    //   smpte240m, linear, log100, log316, iec61966-2-4, bt1361e, iec61966-2-1, bt2020-10, bt2020-12
+uint8_t	uiColorMatrix;				// EColorMatrix; 8 bits in header (corresponds to FFmpeg "colorspace"); 0 - 10 => GBR, bt709,
+                                    //   undef, ???, fcc, bt470bg, smpte170m, smpte240m, YCgCo, bt2020nc, bt2020c
+
 bool            bConstraintSet0Flag;
 bool            bConstraintSet1Flag;
 bool            bConstraintSet2Flag;
--- a/codec/encoder/core/src/au_set.cpp
+++ b/codec/encoder/core/src/au_set.cpp
@@ -202,7 +202,27 @@
 
   BsWriteOneBit (pLocalBitStringAux, false); //aspect_ratio_info_present_flag
   BsWriteOneBit (pLocalBitStringAux, false); //overscan_info_present_flag
-  BsWriteOneBit (pLocalBitStringAux, false); //video_signal_type_present_flag
+
+  // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
+  BsWriteOneBit (pLocalBitStringAux, pSps->bVideoSignalTypePresent); //video_signal_type_present_flag
+  if  ( pSps->bVideoSignalTypePresent )
+  {//write video signal type info to header
+
+    BsWriteBits (pLocalBitStringAux, 3, pSps->uiVideoFormat);
+    BsWriteOneBit (pLocalBitStringAux, pSps->bFullRange);
+    BsWriteOneBit (pLocalBitStringAux, pSps->bColorDescriptionPresent);
+
+    if  ( pSps->bColorDescriptionPresent )
+    {//write color description info to header
+
+      BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorPrimaries);
+      BsWriteBits (pLocalBitStringAux, 8, pSps->uiTransferCharacteristics);
+      BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorMatrix);
+
+    }//write color description info to header
+
+  }//write video signal type info to header
+
   BsWriteOneBit (pLocalBitStringAux, false); //chroma_loc_info_present_flag
   BsWriteOneBit (pLocalBitStringAux, false); //timing_info_present_flag
   BsWriteOneBit (pLocalBitStringAux, false); //nal_hrd_parameters_present_flag
@@ -517,6 +537,16 @@
     pSps->bGapsInFrameNumValueAllowedFlag = true;
 
   pSps->bVuiParamPresentFlag = true;
+
+  // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
+  pSps->bVideoSignalTypePresent =   pLayerParam->bVideoSignalTypePresent;
+  pSps->uiVideoFormat =             pLayerParam->uiVideoFormat;
+  pSps->bFullRange =                pLayerParam->bFullRange;
+  pSps->bColorDescriptionPresent =  pLayerParam->bColorDescriptionPresent;
+  pSps->uiColorPrimaries =          pLayerParam->uiColorPrimaries;
+  pSps->uiTransferCharacteristics = pLayerParam->uiTransferCharacteristics;
+  pSps->uiColorMatrix =             pLayerParam->uiColorMatrix;
+
   return 0;
 }
 
--- a/test/encoder/EncUT_ParameterSetStrategy.cpp
+++ b/test/encoder/EncUT_ParameterSetStrategy.cpp
@@ -120,4 +120,100 @@
   (void) iRet; // Not using iRet at the moment
 }
 
+TEST_F (ParameterSetStrategyTest, TestVSTPParameters) {
+  int32_t iRet = 0;
+  bool FalseLocal = false;	// EXPECT_EQ does not like "true" or "false" as its first arg
+
+  // this test verifies that the client's "video signal type present" parameter values end up in SWelsSPS 
+
+  //init client parameters
+  SEncParamExt sParamExt;
+  SWelsSvcCodingParam::FillDefault(sParamExt);
+  sParamExt.iUsageType = CAMERA_VIDEO_REAL_TIME;
+  sParamExt.iPicWidth = 1280;
+  sParamExt.iPicHeight = 720;
+  sParamExt.iTargetBitrate = 1000000;
+  sParamExt.iRCMode = RC_BITRATE_MODE;
+  sParamExt.fMaxFrameRate = 30.0f;
+
+  // VSTP parameters should be their default values (see SWelsSvcCodingParam::FillDefault())
+  for  ( int i = 0; i < MAX_SPATIAL_LAYER_NUM; i++ )
+  {
+    //         expected    actual
+    EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bVideoSignalTypePresent);
+    EXPECT_EQ( VF_UNDEF,   sParamExt.sSpatialLayers[i].uiVideoFormat);//5
+    EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bFullRange);
+    EXPECT_EQ( FalseLocal, sParamExt.sSpatialLayers[i].bColorDescriptionPresent);
+    EXPECT_EQ( CP_UNDEF,   sParamExt.sSpatialLayers[i].uiColorPrimaries);//2
+    EXPECT_EQ( TRC_UNDEF,  sParamExt.sSpatialLayers[i].uiTransferCharacteristics);//2
+    EXPECT_EQ( CM_UNDEF,   sParamExt.sSpatialLayers[i].uiColorMatrix);//2
+  }
+
+  // set non-default VSTP values
+  sParamExt.iSpatialLayerNum = 2;
+
+  sParamExt.sSpatialLayers[0].bVideoSignalTypePresent   = true;
+  sParamExt.sSpatialLayers[0].uiVideoFormat             = VF_NTSC;//2
+  sParamExt.sSpatialLayers[0].bFullRange                = true;
+  sParamExt.sSpatialLayers[0].bColorDescriptionPresent  = true;
+  sParamExt.sSpatialLayers[0].uiColorPrimaries          = CP_BT709;//1
+  sParamExt.sSpatialLayers[0].uiTransferCharacteristics = TRC_BT709;//1
+  sParamExt.sSpatialLayers[0].uiColorMatrix             = CM_BT709;//1
+
+  sParamExt.sSpatialLayers[1].bVideoSignalTypePresent   = true;
+  sParamExt.sSpatialLayers[1].uiVideoFormat             = VF_PAL;//1
+  sParamExt.sSpatialLayers[1].bFullRange                = true;
+  sParamExt.sSpatialLayers[1].bColorDescriptionPresent  = true;
+  sParamExt.sSpatialLayers[1].uiColorPrimaries          = CP_SMPTE170M;//6
+  sParamExt.sSpatialLayers[1].uiTransferCharacteristics = TRC_SMPTE170M;//6
+  sParamExt.sSpatialLayers[1].uiColorMatrix             = CM_SMPTE170M;//6
+
+  // transcode parameters from client
+  SWelsSvcCodingParam sSvcCodingParam;
+  iRet = sSvcCodingParam.ParamTranscode(sParamExt);
+  EXPECT_EQ (iRet, 0);
+
+  // transcoded VSTP parameters should match the client values
+  for  ( int i = 0; i < sParamExt.iSpatialLayerNum; i++ )
+  {
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].bVideoSignalTypePresent,   sSvcCodingParam.sSpatialLayers[i].bVideoSignalTypePresent);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].uiVideoFormat,             sSvcCodingParam.sSpatialLayers[i].uiVideoFormat);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].bFullRange,                sSvcCodingParam.sSpatialLayers[i].bFullRange);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].bColorDescriptionPresent,  sSvcCodingParam.sSpatialLayers[i].bColorDescriptionPresent);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].uiColorPrimaries,          sSvcCodingParam.sSpatialLayers[i].uiColorPrimaries);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].uiTransferCharacteristics, sSvcCodingParam.sSpatialLayers[i].uiTransferCharacteristics);
+    EXPECT_EQ( sParamExt.sSpatialLayers[i].uiColorMatrix,             sSvcCodingParam.sSpatialLayers[i].uiColorMatrix);
+  }
+
+  // use transcoded parameters to initialize an SWelsSPS
+  m_pSpsArrayPointer = &m_pSpsArray[0];
+  SSpatialLayerConfig* pDlayerParam = &(sSvcCodingParam.sSpatialLayers[0]);
+  iRet = WelsInitSps (
+    m_pSpsArrayPointer,
+    pDlayerParam,
+    &sSvcCodingParam.sDependencyLayers[0],
+    sSvcCodingParam.uiIntraPeriod,
+    sSvcCodingParam.iMaxNumRefFrame,
+    0, //SpsId
+    sSvcCodingParam.bEnableFrameCroppingFlag,
+    sSvcCodingParam.iRCMode != RC_OFF_MODE,
+    0, //DlayerCount
+    false
+    );
+  EXPECT_EQ (iRet, 0);
+
+  // SPS VSTP parameters should match the transcoded values
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bVideoSignalTypePresent,   m_pSpsArrayPointer->bVideoSignalTypePresent);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiVideoFormat,             m_pSpsArrayPointer->uiVideoFormat);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bFullRange,                m_pSpsArrayPointer->bFullRange);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].bColorDescriptionPresent,  m_pSpsArrayPointer->bColorDescriptionPresent);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiColorPrimaries,          m_pSpsArrayPointer->uiColorPrimaries);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiTransferCharacteristics, m_pSpsArrayPointer->uiTransferCharacteristics);
+  EXPECT_EQ( sSvcCodingParam.sSpatialLayers[0].uiColorMatrix,             m_pSpsArrayPointer->uiColorMatrix);
+
+  // TODO: verify that WriteVUI (au_set.cpp) writes the SPS VSTP values to the output file (verified using FFmpeg)
+
+  (void) iRet; // Not using iRet at the moment
+}
+