[x265] [PATCH] add experimental support for interlaced content (field encoding) (refs #15)
Steve Borho
steve at borho.org
Thu Mar 20 04:21:31 CET 2014
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1395285660 18000
# Wed Mar 19 22:21:00 2014 -0500
# Node ID 0f771f867e9cd60a4a57f25156a65be87928d308
# Parent 221d8aee9aa18d049ad533fd893ca863d0416ffb
add experimental support for interlaced content (field encoding) (refs #15)
* adds param.interlaceMode
* removes VUI params that are now handled automatically
* adds --no-interlace --interlace=tff|bff|prog|false CLI options
* signals interlace source flag, clears progressive source flag
This initial implementation requires the user to provide fields (half-height) in
the correct temporal order; so not very useful for exisitng Y4M or YUV
interlaced input files.
When interlacing is enabled, the encoder emits PictureTiming SEI messages that
indicate top or bottom field for the decoder.
diff -r 221d8aee9aa1 -r 0f771f867e9c source/CMakeLists.txt
--- a/source/CMakeLists.txt Wed Mar 19 18:26:14 2014 -0500
+++ b/source/CMakeLists.txt Wed Mar 19 22:21:00 2014 -0500
@@ -18,7 +18,7 @@
include(CheckCXXCompilerFlag)
# X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 9)
+set(X265_BUILD 10)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 221d8aee9aa1 -r 0f771f867e9c source/common/common.h
--- a/source/common/common.h Wed Mar 19 18:26:14 2014 -0500
+++ b/source/common/common.h Wed Mar 19 22:21:00 2014 -0500
@@ -104,7 +104,7 @@
#define X265_LOWRES_CU_SIZE 8
#define X265_LOWRES_CU_BITS 3
-#define MAX_NAL_UNITS 5
+#define MAX_NAL_UNITS 6
#define MIN_FIFO_SIZE 1000
#define X265_MALLOC(type, count) (type*)x265_malloc(sizeof(type) * (count))
diff -r 221d8aee9aa1 -r 0f771f867e9c source/common/param.cpp
--- a/source/common/param.cpp Wed Mar 19 18:26:14 2014 -0500
+++ b/source/common/param.cpp Wed Mar 19 22:21:00 2014 -0500
@@ -193,8 +193,6 @@
param->vui.bEnableChromaLocInfoPresentFlag = 0;
param->vui.chromaSampleLocTypeTopField = 0;
param->vui.chromaSampleLocTypeBottomField = 0;
- param->vui.bEnableFieldSeqFlag = 0;
- param->vui.bEnableFrameFieldInfoPresentFlag = 0;
param->vui.bEnableDefaultDisplayWindowFlag = 0;
param->vui.defDispWinLeftOffset = 0;
param->vui.defDispWinRightOffset = 0;
@@ -572,6 +570,16 @@
p->bFrameAdaptive = atoi(value);
}
}
+ OPT("interlace")
+ {
+ p->interlaceMode = atobool(value);
+ if (bError || p->interlaceMode)
+ {
+ bError = false;
+ p->interlaceMode = parseName(value, x265_interlace_names, bError);
+ }
+ p->vui.bEnableVuiParametersPresentFlag |= !!p->interlaceMode;
+ }
OPT("ref") p->maxNumReferences = atoi(value);
OPT("weightp") p->bEnableWeightedPred = atobool(value);
OPT("cbqpoffs") p->cbQpOffset = atoi(value);
@@ -620,8 +628,6 @@
p->vui.bEnableVideoSignalTypePresentFlag = bvalue;
p->vui.bEnableColorDescriptionPresentFlag = bvalue;
p->vui.bEnableChromaLocInfoPresentFlag = bvalue;
- p->vui.bEnableFieldSeqFlag = bvalue;
- p->vui.bEnableFrameFieldInfoPresentFlag = bvalue;
p->vui.bEnableDefaultDisplayWindowFlag = bvalue;
p->vui.bEnableVuiTimingInfoPresentFlag = bvalue;
p->vui.bEnableVuiHrdParametersPresentFlag = bvalue;
@@ -694,16 +700,6 @@
p->vui.chromaSampleLocTypeTopField = atoi(value);
p->vui.chromaSampleLocTypeBottomField = p->vui.chromaSampleLocTypeTopField;
}
- OPT("fieldseq")
- {
- p->vui.bEnableVuiParametersPresentFlag = 1;
- p->vui.bEnableFieldSeqFlag = atobool(value);
- }
- OPT("framefieldinfo")
- {
- p->vui.bEnableVuiParametersPresentFlag = 1;
- p->vui.bEnableFrameFieldInfoPresentFlag = atobool(value);
- }
OPT("crop-rect")
{
p->vui.bEnableVuiParametersPresentFlag = 1;
@@ -909,6 +905,8 @@
"QP exceeds supported range (-QpBDOffsety to 51)");
CHECK(param->fpsNum == 0 || param->fpsDenom == 0,
"Frame rate numerator and denominator must be specified");
+ CHECK(param->interlaceMode < 0 || param->interlaceMode > 2,
+ "Interlace mode must be 0 (progressive) 1 (top-field first) or 2 (bottom field first)");
CHECK(param->searchMethod<0 || param->searchMethod> X265_FULL_SEARCH,
"Search method is not supported value (0:DIA 1:HEX 2:UMH 3:HM 5:FULL)");
CHECK(param->searchRange < 0,
@@ -1086,6 +1084,10 @@
#if HIGH_BIT_DEPTH
x265_log(param, X265_LOG_INFO, "Internal bit depth : %d\n", param->internalBitDepth);
#endif
+ if (param->interlaceMode)
+ {
+ x265_log(param, X265_LOG_INFO, "Interlaced field inputs : %s\n", x265_interlace_names[param->interlaceMode]);
+ }
x265_log(param, X265_LOG_INFO, "CU size : %d\n", param->maxCUSize);
x265_log(param, X265_LOG_INFO, "Max RQT depth inter / intra : %d / %d\n", param->tuQTMaxInterDepth, param->tuQTMaxIntraDepth);
@@ -1190,6 +1192,7 @@
BOOL(p->bEnableStrongIntraSmoothing, "strong-intra-smoothing");
BOOL(p->bEnableConstrainedIntra, "constrained-intra");
BOOL(p->bOpenGOP, "open-gop");
+ s += sprintf(s, " interlace=%d", p->interlaceMode);
s += sprintf(s, " keyint=%d", p->keyframeMax);
s += sprintf(s, " min-keyint=%d", p->keyframeMin);
s += sprintf(s, " scenecut=%d", p->scenecutThreshold);
diff -r 221d8aee9aa1 -r 0f771f867e9c source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Wed Mar 19 18:26:14 2014 -0500
+++ b/source/encoder/encoder.cpp Wed Mar 19 22:21:00 2014 -0500
@@ -959,8 +959,8 @@
profileTierLevel.setTierFlag(m_levelTier ? true : false);
profileTierLevel.setProfileIdc(m_profile);
profileTierLevel.setProfileCompatibilityFlag(m_profile, 1);
- profileTierLevel.setProgressiveSourceFlag(m_progressiveSourceFlag);
- profileTierLevel.setInterlacedSourceFlag(m_interlacedSourceFlag);
+ profileTierLevel.setProgressiveSourceFlag(!param->interlaceMode);
+ profileTierLevel.setInterlacedSourceFlag(!!param->interlaceMode);
profileTierLevel.setNonPackedConstraintFlag(m_nonPackedConstraintFlag);
profileTierLevel.setFrameOnlyConstraintFlag(m_frameOnlyConstraintFlag);
@@ -1072,8 +1072,8 @@
vui->setChromaSampleLocTypeBottomField(param->vui.chromaSampleLocTypeBottomField);
vui->setNeutralChromaIndicationFlag(m_neutralChromaIndicationFlag);
vui->setDefaultDisplayWindow(m_defaultDisplayWindow);
- vui->setFrameFieldInfoPresentFlag(param->vui.bEnableFrameFieldInfoPresentFlag);
- vui->setFieldSeqFlag(param->vui.bEnableFieldSeqFlag);
+ vui->setFrameFieldInfoPresentFlag(!!param->interlaceMode);
+ vui->setFieldSeqFlag(!!param->interlaceMode);
vui->setHrdParametersPresentFlag(param->vui.bEnableVuiHrdParametersPresentFlag);
vui->getHrdParameters()->setNalHrdParametersPresentFlag(param->vui.bEnableNalHrdParametersPresentFlag);
vui->getHrdParameters()->setSubPicHrdParamsPresentFlag(param->vui.bEnableSubPicHrdParamsPresentFlag);
@@ -1411,6 +1411,10 @@
x265_log(p, X265_LOG_WARNING, "!! HEVC Range Extension specifications are not finalized !!\n");
x265_log(p, X265_LOG_WARNING, "!! This output bitstream may not be compliant with the final spec !!\n");
}
+ if (p->interlaceMode)
+ {
+ x265_log(p, X265_LOG_WARNING, "Support for interlaced video is experimental\n");
+ }
m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
@@ -1482,13 +1486,10 @@
m_maxNumOffsetsPerPic = 2048;
m_log2ParallelMergeLevelMinus2 = 0;
- m_progressiveSourceFlag = true;
- m_interlacedSourceFlag = false;
m_nonPackedConstraintFlag = false;
m_frameOnlyConstraintFlag = false;
m_recoveryPointSEIEnabled = 0;
m_bufferingPeriodSEIEnabled = 0;
- m_pictureTimingSEIEnabled = 0;
m_displayOrientationSEIAngle = 0;
m_gradualDecodingRefreshInfoEnabled = 0;
m_decodingUnitInfoSEIEnabled = 0;
diff -r 221d8aee9aa1 -r 0f771f867e9c source/encoder/encoder.h
--- a/source/encoder/encoder.h Wed Mar 19 18:26:14 2014 -0500
+++ b/source/encoder/encoder.h Wed Mar 19 22:21:00 2014 -0500
@@ -116,8 +116,6 @@
Level::Tier m_levelTier;
Level::Name m_level;
- bool m_progressiveSourceFlag;
- bool m_interlacedSourceFlag;
bool m_nonPackedConstraintFlag;
bool m_frameOnlyConstraintFlag;
@@ -157,7 +155,6 @@
bool m_loopFilterAcrossTilesEnabledFlag;
int m_bufferingPeriodSEIEnabled;
- int m_pictureTimingSEIEnabled;
int m_recoveryPointSEIEnabled;
int m_displayOrientationSEIAngle;
int m_gradualDecodingRefreshInfoEnabled;
diff -r 221d8aee9aa1 -r 0f771f867e9c source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Wed Mar 19 18:26:14 2014 -0500
+++ b/source/encoder/frameencoder.cpp Wed Mar 19 22:21:00 2014 -0500
@@ -136,11 +136,11 @@
top->initPPS(&m_pps);
m_sps.setNumLongTermRefPicSPS(0);
- if (m_cfg->m_pictureTimingSEIEnabled || m_cfg->m_decodingUnitInfoSEIEnabled)
+ if (m_cfg->m_decodingUnitInfoSEIEnabled)
{
m_sps.setHrdParameters(m_cfg->param->fpsNum, m_cfg->param->fpsDenom, 0, m_cfg->param->rc.bitrate, m_cfg->param->bframes > 0);
}
- if (m_cfg->m_bufferingPeriodSEIEnabled || m_cfg->m_pictureTimingSEIEnabled || m_cfg->m_decodingUnitInfoSEIEnabled)
+ if (m_cfg->m_bufferingPeriodSEIEnabled || m_cfg->m_decodingUnitInfoSEIEnabled)
{
m_sps.getVuiParameters()->setHrdParametersPresentFlag(true);
}
@@ -500,6 +500,26 @@
}
}
+ if (!!m_cfg->param->interlaceMode)
+ {
+ OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI);
+
+ SEIPictureTiming sei;
+ sei.m_picStruct = (slice->getPOC() & 1) && m_cfg->param->interlaceMode == 1 ? 1 /* top */ : 2 /* bot */;
+ sei.m_sourceScanType = 1;
+ sei.m_duplicateFlag = 0;
+
+ entropyCoder->setBitstream(&nalu.m_bitstream);
+ m_seiWriter.writeSEImessage(nalu.m_bitstream, sei, &m_sps);
+ writeRBSPTrailingBits(nalu.m_bitstream);
+ m_nalList[m_nalCount] = X265_MALLOC(NALUnitEBSP, 1);
+ if (m_nalList[m_nalCount])
+ {
+ m_nalList[m_nalCount]->init(nalu);
+ m_nalCount++;
+ }
+ }
+
/* use the main bitstream buffer for storing the marshaled picture */
if (m_sps.getUseSAO())
{
diff -r 221d8aee9aa1 -r 0f771f867e9c source/x265.cpp
--- a/source/x265.cpp Wed Mar 19 18:26:14 2014 -0500
+++ b/source/x265.cpp Wed Mar 19 22:21:00 2014 -0500
@@ -76,6 +76,8 @@
{ "input-depth", required_argument, NULL, 0 },
{ "input-res", required_argument, NULL, 0 },
{ "input-csp", required_argument, NULL, 0 },
+ { "interlace", required_argument, NULL, 0 },
+ { "no-interlace", no_argument, NULL, 0 },
{ "fps", required_argument, NULL, 0 },
{ "seek", required_argument, NULL, 0 },
{ "frame-skip", required_argument, NULL, 0 },
@@ -388,9 +390,6 @@
H0(" --colormatrix <string> Specify color matrix setting from undef, bt709, fcc, bt470bg, smpte170m,\n");
H0(" smpte240m, GBR, YCgCo, bt2020nc, bt2020c. Default undef\n");
H0(" --chromaloc <integer> Specify chroma sample location (0 to 5). Default of %d\n", param->vui.chromaSampleLocTypeTopField);
- H0(" --[no-]fieldseq Specify that pictures are fields and an SEI timing message\n");
- H0(" will be added to every access unit. Default %s\n", OPT(param->vui.bEnableFieldSeqFlag));
- H0(" --[no-]framefieldinfo Specify that a pic-struct will be added to the SEI timing message. Default %s\n", OPT(param->vui.bEnableFrameFieldInfoPresentFlag));
H0(" --[no-]timinginfo Add timing information to the VUI. Defaut %s\n", OPT(param->vui.bEnableVuiTimingInfoPresentFlag));
H0(" --[no-]hrd Signal HRD information. Default %s\n", OPT(param->vui.bEnableVuiHrdParametersPresentFlag));
H0(" --nal-hrd <string> Signal NAL HRD information (requires vbv-buffer size) Choose from none, vbr or cbr.Default none\n");
diff -r 221d8aee9aa1 -r 0f771f867e9c source/x265.h
--- a/source/x265.h Wed Mar 19 18:26:14 2014 -0500
+++ b/source/x265.h Wed Mar 19 22:21:00 2014 -0500
@@ -293,6 +293,7 @@
static const char * const x265_sar_names[] = { "undef", "1:1", "12:11", "10:11", "16:11", "40:33", "24:11", "20:11",
"32:11", "80:33", "18:11", "15:11", "64:33", "160:99", "4:3", "3:2", "2:1", 0 };
static const char * const x265_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
+static const char * const x265_interlace_names[] = { "prog", "tff", "bff", 0 };
/* x265 input parameters
*
@@ -382,6 +383,12 @@
* minimum requirement. All valid HEVC heights are supported */
int sourceHeight;
+ /* Interlace type of source pictures. 0 - progressive pictures (default).
+ * 1 - top field first, 2 - bottom field first. HEVC encodes interlaced
+ * content as fields, they must be provided to the encoder in the correct
+ * temporal order. EXPERIMENTAL */
+ int interlaceMode;
+
/*== Coding Unit (CU) definitions ==*/
/* Maxiumum CU width and height in pixels. The size must be 64, 32, or 16.
@@ -769,16 +776,6 @@
* the bottom field. The default is 0 */
int chromaSampleLocTypeBottomField;
- /* Field seq flag specifies that the pictures are fields and each one
- * has a timing SEI message. The default is false */
- int bEnableFieldSeqFlag;
-
- /* Frame field info present flag indicates that each picture has a
- * timing SEI message wich includes a pic_struct, source_scan_type and
- * duplicate_flag elements. If not set then the pic_struct element is
- * not included. The default is false */
- int bEnableFrameFieldInfoPresentFlag;
-
/* Default display window flag adds def_disp_win_left_offset,
* def_disp_win_right_offset, def_disp_win_top_offset and
* def_disp_win_bottom_offset to the VUI. The default is false */
More information about the x265-devel
mailing list