Added support for "video signal type present" information.

The "Video signal type present" information is written to the output
video file when it is created, and later is used by the decoder to
properly decode the compressed video data. The saved attributes
are:

- format type (PAL, NTSC, etc.)
- color primaries (BT709, SMPTE170M, etc.)
- transfer characteristics (BT709, SMPTE170M, etc.)
- color matrix ((BT709, SMPTE170M, etc.)

These modifications allow the client to specify these attributes
and, if specified, makes sure they are written to the output file.
This commit is contained in:
Gregory J. Wolfe 2016-02-23 13:21:06 -05:00
parent f35a0daccf
commit c7fcba06c7
6 changed files with 113 additions and 31 deletions

View File

@ -1,4 +1,4 @@
# Contributors to the OpenH264 project
# Contributors to the OpenH264 project
Patrick Ai
Sijia Chen
@ -35,6 +35,7 @@ James Wang
Juanny Wang
Zhiliang Wang
Hervé Willems
Gregory J Wolfe
Katherine Wu
Guang Xu
Jeffery Xu

View File

@ -343,8 +343,6 @@ typedef struct {
unsigned int uiSliceSizeConstraint; ///< now only used when uiSliceMode=4
} SSliceArgument;
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
/**
* @brief Enumerate the type of video format
*/
@ -416,8 +414,6 @@ typedef enum {
CM_NUM_ENUM
} EColorMatrix;
// ... end 02/18/2016
/**
* @brief Structure for spatial layer configuration
*/
@ -433,8 +429,7 @@ typedef struct {
SSliceArgument sSliceArgument;
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See also parameter_sets.h.
// 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]
@ -445,7 +440,6 @@ typedef struct {
// 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
// ... end 02/18/2016
} SSpatialLayerConfig;
/**

View File

@ -191,9 +191,8 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
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
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See codec_app_def.h for more info. The default values preserve the previous behavior; i.e., no
// additional information will be written to the output file.
// 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]
@ -201,7 +200,6 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
param.sSpatialLayers[iLayer].uiColorPrimaries = CP_UNDEF; // undefined
param.sSpatialLayers[iLayer].uiTransferCharacteristics = TRC_UNDEF; // undefined
param.sSpatialLayers[iLayer].uiColorMatrix = CM_UNDEF; // undefined
// ... end 02/18/2016
}
}
@ -420,8 +418,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
pSpatialLayer->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp;
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See codec_app_def.h and parameter_sets.h for more info.
// 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;
@ -429,7 +426,6 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
pSpatialLayer->uiColorPrimaries = pCodingParam.sSpatialLayers[iIdxSpatial].uiColorPrimaries;
pSpatialLayer->uiTransferCharacteristics = pCodingParam.sSpatialLayers[iIdxSpatial].uiTransferCharacteristics;
pSpatialLayer->uiColorMatrix = pCodingParam.sSpatialLayers[iIdxSpatial].uiColorMatrix;
// ... end 02/18/2016
uiProfileIdc = (!bSimulcastAVC) ? PRO_SCALABLE_BASELINE : PRO_BASELINE;
++ pDlp;

View File

@ -79,15 +79,8 @@ bool bVuiParamPresentFlag;
// bool bTimingInfoPresentFlag;
// bool bFixedFrameRateFlag;
bool bConstraintSet0Flag;
bool bConstraintSet1Flag;
bool bConstraintSet2Flag;
bool bConstraintSet3Flag;
// bool bSeparateColorPlaneFlag; // =false,: only used in decoder, encoder in general_***; it can be removed when removed general up_sample
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See also codec_app_def.h for definitions of enumerators EVideoFormatSPS, EColorPrimaries, ETransferCharacteristics,
// and EColorMatrix.
// 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]
@ -98,7 +91,12 @@ uint8_t uiTransferCharacteristics; // ETransferCharacteristics; 8 bits in header
// 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
// ... end 02/18/2016
bool bConstraintSet0Flag;
bool bConstraintSet1Flag;
bool bConstraintSet2Flag;
bool bConstraintSet3Flag;
// bool bSeparateColorPlaneFlag; // =false,: only used in decoder, encoder in general_***; it can be removed when removed general up_sample
} SWelsSPS, *PWelsSPS;

View File

@ -203,8 +203,7 @@ int32_t WelsWriteVUI (SWelsSPS* pSps, SBitStringAux* pBitStringAux) {
BsWriteOneBit (pLocalBitStringAux, false); //aspect_ratio_info_present_flag
BsWriteOneBit (pLocalBitStringAux, false); //overscan_info_present_flag
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See parameter_sets.h for more info.
// 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
@ -223,7 +222,6 @@ int32_t WelsWriteVUI (SWelsSPS* pSps, SBitStringAux* pBitStringAux) {
}//write color description info to header
}//write video signal type info to header
// ... end 02/18/2016
BsWriteOneBit (pLocalBitStringAux, false); //chroma_loc_info_present_flag
BsWriteOneBit (pLocalBitStringAux, false); //timing_info_present_flag
@ -540,8 +538,7 @@ int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialL
pSps->bVuiParamPresentFlag = true;
// 02/18/2016, Greg Wolfe, Kodak Alaris: Added support for "video signal type present" information.
// See codec_app_def.h and parameter_sets.h for more info.
// 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;
@ -549,7 +546,6 @@ int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialL
pSps->uiColorPrimaries = pLayerParam->uiColorPrimaries;
pSps->uiTransferCharacteristics = pLayerParam->uiTransferCharacteristics;
pSps->uiColorMatrix = pLayerParam->uiColorMatrix;
// ... end 02/18/2016
return 0;
}

View File

@ -120,4 +120,101 @@ TEST_F (ParameterSetStrategyTest, FindExistingSps) {
(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
bool TrueLocal = true;
// 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
}