<div dir="ltr"><span style="color:rgb(80,0,80)"># HG changeset patch</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"># User Shushuang <</span><a href="mailto:shushang@multicorewareinc.com" target="_blank">shushang@multicorewareinc.com</a><span style="color:rgb(80,0,80)">></span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"># Date 1558582124 -28800</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"># Thu May 23 11:28:44 2019 +0800</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"># Node ID 220cdb4328a1e2c7419546b50c4d07</span><span style="color:rgb(80,0,80)">e652ae1537</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"># Parent 3f4fb9a2ac6817c9be4acab5c87746</span><span style="color:rgb(80,0,80)">d405fcffd4</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)">Add codes to support field feature</span> <div><br></div><div>Pushed patch to x265 default public repo.</div><div><br></div><div>Thanks & Regards,</div><div>Dinesh <br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, May 23, 2019 at 12:00 PM <<a href="mailto:santhoshini@multicorewareinc.com">santhoshini@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"># HG changeset patch<br>
# User Shushuang <<a href="mailto:shushang@multicorewareinc.com" target="_blank">shushang@multicorewareinc.com</a>><br>
# Date 1558582124 -28800<br>
# Thu May 23 11:28:44 2019 +0800<br>
# Node ID 220cdb4328a1e2c7419546b50c4d07e652ae1537<br>
# Parent 3f4fb9a2ac6817c9be4acab5c87746d405fcffd4<br>
Add codes to support field feature<br>
<br>
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst<br>
+++ b/doc/reST/cli.rst<br>
@@ -551,6 +551,10 @@<br>
This feature can be enabled only in closed GOP structures.<br>
Default 0 (disabled).<br>
<br>
+.. option:: --field, --no-field<br>
+<br>
+ Enable or disable field coding. Default disabled.<br>
+ <br>
Profile, Level, Tier<br>
====================<br>
<br>
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt<br>
+++ b/source/CMakeLists.txt<br>
@@ -29,7 +29,7 @@<br>
option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br>
mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br>
# X265_BUILD must be incremented each time the public API is changed<br>
-set(X265_BUILD 174)<br>
+set(X265_BUILD 175)<br>
configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" target="_blank">x265.def.in</a>"<br>
"${PROJECT_BINARY_DIR}/x265.def")<br>
configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265_config.h.in" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
diff --git a/source/common/frame.cpp b/source/common/frame.cpp<br>
--- a/source/common/frame.cpp<br>
+++ b/source/common/frame.cpp<br>
@@ -56,6 +56,7 @@<br>
m_addOnCtuInfo = NULL;<br>
m_addOnPrevChange = NULL;<br>
m_classifyFrame = false;<br>
+ m_fieldNum = 0;<br>
}<br>
<br>
bool Frame::create(x265_param *param, float* quantOffsets)<br>
diff --git a/source/common/frame.h b/source/common/frame.h<br>
--- a/source/common/frame.h<br>
+++ b/source/common/frame.h<br>
@@ -129,6 +129,7 @@<br>
uint32_t* m_classifyCount;<br>
<br>
bool m_classifyFrame;<br>
+ int m_fieldNum;<br>
<br>
Frame();<br>
<br>
diff --git a/source/common/param.cpp b/source/common/param.cpp<br>
--- a/source/common/param.cpp<br>
+++ b/source/common/param.cpp<br>
@@ -140,6 +140,7 @@<br>
param->uhdBluray = 0;<br>
param->bHighTier = 1; //Allow high tier by default<br>
param->interlaceMode = 0;<br>
+ param->bField = 0;<br>
param->bAnnexB = 1;<br>
param->bRepeatHeaders = 0;<br>
param->bEnableAccessUnitDelimiters = 0;<br>
@@ -1267,6 +1268,7 @@<br>
OPT("svt-fps-in-vps") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name);<br>
#endif<br>
OPT("fades") p->bEnableFades = atobool(value);<br>
+ OPT("field") p->bField = atobool( value );<br>
else<br>
return X265_PARAM_BAD_NAME;<br>
}<br>
@@ -1639,6 +1641,12 @@<br>
if (param->dolbyProfile == 81)<br>
CHECK(!(param->masteringDisplayColorVolume), "Dolby Vision profile - 8.1 requires Mastering display color volume information\n");<br>
}<br>
+<br>
+ if (param->bField && param->interlaceMode)<br>
+ {<br>
+ CHECK( (param->bFrameAdaptive==0), "Adaptive B-frame decision method should be closed for field feature.\n" );<br>
+ // to do<br>
+ }<br>
#if !X86_64<br>
CHECK(param->searchMethod == X265_SEA && (param->sourceWidth > 840 || param->sourceHeight > 480),<br>
"SEA motion search does not support resolutions greater than 480p in 32 bit build");<br>
@@ -2045,6 +2053,7 @@<br>
BOOL(p->bSingleSeiNal, "single-sei");<br>
BOOL(p->rc.hevcAq, "hevc-aq");<br>
BOOL(p->bEnableSvtHevc, "svt");<br>
+ BOOL(p->bField, "field");<br>
s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange);<br>
#undef BOOL<br>
return buf;<br>
@@ -2370,6 +2379,7 @@<br>
dst->dolbyProfile = src->dolbyProfile;<br>
dst->bEnableSvtHevc = src->bEnableSvtHevc;<br>
dst->bEnableFades = src->bEnableFades;<br>
+ dst->bField = src->bField;<br>
<br>
#ifdef SVT_HEVC<br>
memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION));<br>
diff --git a/source/common/slice.h b/source/common/slice.h<br>
--- a/source/common/slice.h<br>
+++ b/source/common/slice.h<br>
@@ -361,6 +361,7 @@<br>
int numRefIdxDefault[2];<br>
int m_iNumRPSInSPS;<br>
const x265_param *m_param;<br>
+ int m_fieldNum;<br>
<br>
Slice()<br>
{<br>
@@ -376,6 +377,7 @@<br>
numRefIdxDefault[1] = 1;<br>
m_rpsIdx = -1;<br>
m_chromaQpOffset[0] = m_chromaQpOffset[1] = 0;<br>
+ m_fieldNum = 0;<br>
}<br>
<br>
void disableWeights();<br>
diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp<br>
--- a/source/encoder/dpb.cpp<br>
+++ b/source/encoder/dpb.cpp<br>
@@ -127,6 +127,7 @@<br>
{<br>
Slice* slice = newFrame->m_encData->m_slice;<br>
slice->m_poc = newFrame->m_poc;<br>
+ slice->m_fieldNum = newFrame->m_fieldNum;<br>
<br>
int pocCurr = slice->m_poc;<br>
int type = newFrame->m_lowres.sliceType;<br>
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp<br>
+++ b/source/encoder/encoder.cpp<br>
@@ -1107,6 +1107,8 @@<br>
inFrame->m_pts = pic_in->pts;<br>
inFrame->m_forceqp = pic_in->forceqp;<br>
inFrame->m_param = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;<br>
+ if (m_param->bField && m_param->interlaceMode)<br>
+ inFrame->m_fieldNum = pic_in->fieldNum;<br>
<br>
copyUserSEIMessages(inFrame, pic_in);<br>
<br>
diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp<br>
--- a/source/encoder/frameencoder.cpp<br>
+++ b/source/encoder/frameencoder.cpp<br>
@@ -686,10 +686,25 @@<br>
<br>
if (vui->frameFieldInfoPresentFlag)<br>
{<br>
- if (m_param->interlaceMode == 2)<br>
- sei->m_picStruct = (poc & 1) ? 1 /* top */ : 2 /* bottom */;<br>
- else if (m_param->interlaceMode == 1)<br>
- sei->m_picStruct = (poc & 1) ? 2 /* bottom */ : 1 /* top */;<br>
+ if (m_param->interlaceMode > 0)<br>
+ {<br>
+ if( m_param->interlaceMode == 2 )<br>
+ { <br>
+ // m_picStruct should be set to 3 or 4 when field feature is enabled<br>
+ if (m_param->bField)<br>
+ // 3: Top field, bottom field, in that order; 4: Bottom field, top field, in that order<br>
+ sei->m_picStruct = (slice->m_fieldNum == 1) ? 4 : 3;<br>
+ else<br>
+ sei->m_picStruct = (poc & 1) ? 1 /* top */ : 2 /* bottom */;<br>
+ } <br>
+ else if (m_param->interlaceMode == 1)<br>
+ {<br>
+ if (m_param->bField)<br>
+ sei->m_picStruct = (slice->m_fieldNum == 1) ? 3: 4;<br>
+ else<br>
+ sei->m_picStruct = (poc & 1) ? 2 /* bottom */ : 1 /* top */;<br>
+ }<br>
+ }<br>
else<br>
sei->m_picStruct = m_param->pictureStructure;<br>
<br>
diff --git a/source/x265.cpp b/source/x265.cpp<br>
--- a/source/x265.cpp<br>
+++ b/source/x265.cpp<br>
@@ -575,6 +575,15 @@<br>
info.timebaseNum = param->fpsDenom;<br>
info.timebaseDenom = param->fpsNum;<br>
<br>
+ if (param->bField && param->interlaceMode)<br>
+ { // Field FPS<br>
+ param->fpsNum *= 2;<br>
+ // Field height<br>
+ param->sourceHeight = param->sourceHeight >> 1;<br>
+ // Number of fields to encode<br>
+ param->totalFrames *= 2;<br>
+ }<br>
+<br>
if (api->param_apply_profile(param, profile))<br>
return true;<br>
<br>
@@ -916,7 +925,8 @@<br>
bool bDolbyVisionRPU = false;<br>
uint8_t *rpuPayload = NULL;<br>
int ret = 0;<br>
-<br>
+ int inputPicNum = 1;<br>
+ x265_picture picField1, picField2;<br>
<br>
if (!param->bRepeatHeaders && !param->bEnableSvtHevc)<br>
{<br>
@@ -930,7 +940,16 @@<br>
cliopt.totalbytes += cliopt.output->writeHeaders(p_nal, nal);<br>
}<br>
<br>
- api->picture_init(param, pic_in);<br>
+ if (param->bField && param->interlaceMode)<br>
+ {<br>
+ api->picture_init(param, &picField1);<br>
+ api->picture_init(param, &picField2);<br>
+ // return back the original height of input<br>
+ param->sourceHeight *= 2;<br>
+ api->picture_init(param, pic_in);<br>
+ }<br>
+ else<br>
+ api->picture_init(param, pic_in);<br>
<br>
if (param->dolbyProfile && cliopt.dolbyVisionRpu)<br>
{<br>
@@ -952,7 +971,7 @@<br>
// main encoder loop<br>
while (pic_in && !b_ctrl_c)<br>
{<br>
- pic_orig.poc = inFrameCount;<br>
+ pic_orig.poc = (param->bField && param->interlaceMode) ? inFrameCount * 2 : inFrameCount;<br>
if (cliopt.qpfile)<br>
{<br>
if (!cliopt.parseQPFile(pic_orig))<br>
@@ -980,39 +999,128 @@<br>
/* Overwrite PTS */<br>
pic_in->pts = pic_in->poc;<br>
<br>
+ // convert to field<br>
+ if (param->bField && param->interlaceMode)<br>
+ {<br>
+ int height = pic_in->height >> 1;<br>
+ <br>
+ int static bCreated = 0;<br>
+ if (bCreated == 0)<br>
+ {<br>
+ bCreated = 1;<br>
+ inputPicNum = 2;<br>
+ picField1.fieldNum = 1;<br>
+ picField2.fieldNum = 2;<br>
+<br>
+ picField1.bitDepth = picField2.bitDepth = pic_in->bitDepth;<br>
+ picField1.colorSpace = picField2.colorSpace = pic_in->colorSpace;<br>
+ picField1.height = picField2.height = pic_in->height >> 1;<br>
+ picField1.framesize = picField2.framesize = pic_in->framesize >> 1;<br>
+<br>
+ char* field1Buf = X265_MALLOC( char, pic_in->framesize >> 1 );<br>
+ char* field2Buf = X265_MALLOC( char, pic_in->framesize >> 1 );<br>
+ <br>
+ int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0];<br>
+ int framesize = stride * (height >> x265_cli_csps[pic_in->colorSpace].height[0]);<br>
+ picField1.planes[0] = field1Buf;<br>
+ picField2.planes[0] = field2Buf;<br>
+ for (int i = 1; i < x265_cli_csps[pic_in->colorSpace].planes; i++)<br>
+ {<br>
+ picField1.planes[i] = field1Buf + framesize;<br>
+ picField2.planes[i] = field2Buf + framesize;<br>
+<br>
+ stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i];<br>
+ framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[i]));<br>
+ }<br>
+ assert(framesize == picField1.framesize);<br>
+ }<br>
+<br>
+ picField1.pts = picField1.poc = pic_in->poc;<br>
+ picField2.pts = picField2.poc = pic_in->poc + 1;<br>
+<br>
+ picField1.userSEI = picField2.userSEI = pic_in->userSEI;<br>
+<br>
+ //if (pic_in->userData)<br>
+ //{<br>
+ // // Have to handle userData here<br>
+ //}<br>
+<br>
+ if (pic_in->framesize)<br>
+ {<br>
+ for (int i = 0; i < x265_cli_csps[pic_in->colorSpace].planes; i++)<br>
+ {<br>
+ char* srcP1 = (char*)pic_in->planes[i];<br>
+ char* srcP2 = (char*)pic_in->planes[i] + pic_in->stride[i];<br>
+ char* p1 = (char*)picField1.planes[i];<br>
+ char* p2 = (char*)picField2.planes[i];<br>
+<br>
+ int stride = picField1.stride[i];<br>
+<br>
+ for (int y = 0; y < (height >> x265_cli_csps[pic_in->colorSpace].height[i]); y++)<br>
+ {<br>
+ memcpy(p1, srcP1, stride);<br>
+ memcpy(p2, srcP2, stride);<br>
+ srcP1 += 2*stride;<br>
+ srcP2 += 2*stride;<br>
+ p1 += stride;<br>
+ p2 += stride;<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
if (bDolbyVisionRPU)<br>
{<br>
- if (rpuParser(pic_in, cliopt.dolbyVisionRpu) > 0)<br>
- goto fail;<br>
+ if (param->bField && param->interlaceMode)<br>
+ {<br>
+ if (rpuParser(&picField1, cliopt.dolbyVisionRpu) > 0)<br>
+ goto fail;<br>
+ if (rpuParser(&picField2, cliopt.dolbyVisionRpu) > 0)<br>
+ goto fail;<br>
+ }<br>
+ else<br>
+ {<br>
+ if (rpuParser(pic_in, cliopt.dolbyVisionRpu) > 0)<br>
+ goto fail;<br>
+ }<br>
}<br>
}<br>
- int numEncoded = api->encoder_encode(encoder, &p_nal, &nal, pic_in, pic_recon);<br>
- if (numEncoded < 0)<br>
- {<br>
- b_ctrl_c = 1;<br>
- ret = 4;<br>
- break;<br>
+ <br>
+ for (int inputNum = 0; inputNum < inputPicNum; inputNum++)<br>
+ { <br>
+ x265_picture *picInput = NULL;<br>
+ if (inputPicNum == 2)<br>
+ picInput = pic_in ? (inputNum ? &picField2 : &picField1) : NULL;<br>
+ else<br>
+ picInput = pic_in;<br>
+<br>
+ int numEncoded = api->encoder_encode( encoder, &p_nal, &nal, picInput, pic_recon );<br>
+ if( numEncoded < 0 )<br>
+ {<br>
+ b_ctrl_c = 1;<br>
+ ret = 4;<br>
+ break;<br>
+ }<br>
+<br>
+ if (reconPlay && numEncoded)<br>
+ reconPlay->writePicture(*pic_recon);<br>
+<br>
+ outFrameCount += numEncoded;<br>
+<br>
+ if (numEncoded && pic_recon && cliopt.recon)<br>
+ cliopt.recon->writePicture(pic_out);<br>
+ if (nal)<br>
+ {<br>
+ cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);<br>
+ if (pts_queue)<br>
+ {<br>
+ pts_queue->push(-pic_out.pts);<br>
+ if (pts_queue->size() > 2)<br>
+ pts_queue->pop();<br>
+ }<br>
+ }<br>
+ cliopt.printStatus( outFrameCount );<br>
}<br>
-<br>
- if (reconPlay && numEncoded)<br>
- reconPlay->writePicture(*pic_recon);<br>
-<br>
- outFrameCount += numEncoded;<br>
-<br>
- if (numEncoded && pic_recon && cliopt.recon)<br>
- cliopt.recon->writePicture(pic_out);<br>
- if (nal)<br>
- {<br>
- cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);<br>
- if (pts_queue)<br>
- {<br>
- pts_queue->push(-pic_out.pts);<br>
- if (pts_queue->size() > 2)<br>
- pts_queue->pop();<br>
- }<br>
- }<br>
-<br>
- cliopt.printStatus(outFrameCount);<br>
}<br>
<br>
/* Flush the encoder */<br>
diff --git a/source/x265.h b/source/x265.h<br>
--- a/source/x265.h<br>
+++ b/source/x265.h<br>
@@ -464,6 +464,8 @@<br>
<br>
//Dolby Vision RPU metadata<br>
x265_dolby_vision_rpu rpu;<br>
+ <br>
+ int fieldNum;<br>
} x265_picture;<br>
<br>
typedef enum<br>
@@ -1775,6 +1777,9 @@<br>
/* Detect fade-in regions. Enforces I-slice for the brightest point.<br>
Re-init RC history at that point in ABR mode. Default is disabled. */<br>
int bEnableFades;<br>
+<br>
+ /* Enable field coding */<br>
+ int bField;<br>
} x265_param;<br>
/* x265_param_alloc:<br>
* Allocates an x265_param instance. The returned param structure is not<br>
diff --git a/source/x265cli.h b/source/x265cli.h<br>
--- a/source/x265cli.h<br>
+++ b/source/x265cli.h<br>
@@ -73,6 +73,8 @@<br>
{ "input-csp", required_argument, NULL, 0 },<br>
{ "interlace", required_argument, NULL, 0 },<br>
{ "no-interlace", no_argument, NULL, 0 },<br>
+ { "field", no_argument, NULL, 0 },<br>
+ { "no-field", no_argument, NULL, 0 },<br>
{ "fps", required_argument, NULL, 0 },<br>
{ "seek", required_argument, NULL, 0 },<br>
{ "frame-skip", required_argument, NULL, 0 },<br>
@@ -391,6 +393,7 @@<br>
H0("-f/--frames <integer> Maximum number of frames to encode. Default all\n");<br>
H0(" --seek <integer> First frame to encode\n");<br>
H1(" --[no-]interlace <bff|tff> Indicate input pictures are interlace fields in temporal order. Default progressive\n");<br>
+ H0(" --[no-]field Enable or disable field coding. Default %s\n", OPT( param->bField));<br>
H1(" --dither Enable dither if downscaling to 8 bit pixels. Default disabled\n");<br>
H0(" --[no-]copy-pic Copy buffers of input picture in frame. Default %s\n", OPT(param->bCopyPicToFrame));<br>
H0("\nQuality reporting metrics:\n");<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div>