[x265] [PATCH] Add codes to support field feature

Dinesh Kumar Reddy dinesh at multicorewareinc.com
Thu May 23 13:45:41 CEST 2019


# HG changeset patch
# User Shushuang <shushang at multicorewareinc.com>
# Date 1558582124 -28800
#      Thu May 23 11:28:44 2019 +0800
# Node ID 220cdb4328a1e2c7419546b50c4d07e652ae1537
# Parent  3f4fb9a2ac6817c9be4acab5c87746d405fcffd4
Add codes to support field feature

Pushed patch to x265 default public repo.

Thanks & Regards,
Dinesh

On Thu, May 23, 2019 at 12:00 PM <santhoshini at multicorewareinc.com> wrote:

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


More information about the x265-devel mailing list