[x265] [PATCH 2 of 2] abr-ladder: Parse config file and launch ABR tiers

Aruna Matheswaran aruna at multicorewareinc.com
Mon Apr 13 16:35:53 CEST 2020


On Thu, Apr 9, 2020 at 2:40 PM Kavitha Sampath <kavitha at multicorewareinc.com>
wrote:

>
>
> On Tue, Mar 31, 2020 at 6:22 PM Aruna Matheswaran <
> aruna at multicorewareinc.com> wrote:
>
>> # HG changeset patch
>> # User Aruna Matheswaran <aruna at multicorewareinc.com>
>> # Date 1585653210 -19800
>> #      Tue Mar 31 16:43:30 2020 +0530
>> # Node ID d78121f6445e01f55c2ac7728bdb12c8850fa2f9
>> # Parent  3eccfeafc04000b68c25ab52c43741a1acac21c8
>> abr-ladder: Parse config file and launch ABR tiers
>>
>> diff -r 3eccfeafc040 -r d78121f6445e doc/reST/cli.rst
>> --- a/doc/reST/cli.rst  Wed Feb 26 16:37:13 2020 +0530
>> +++ b/doc/reST/cli.rst  Tue Mar 31 16:43:30 2020 +0530
>> @@ -2520,6 +2520,28 @@
>>         --recon-y4m-exec "ffplay -i pipe:0 -autoexit"
>>
>>         **CLI ONLY**
>> +
>> +ABR-ladder Options
>> +==================
>> +
>> +.. option:: --abr-ladder <filename>
>> +
>> +       File containing the encoder configurations to generate ABR ladder.
>> +       The format of each line is:
>> +
>> +       **<encID:reuse-level:refID> <CLI>**
>> +
>> +       where, encID indicates the unique name given to the encode, refID
>> indicates
>> +       the name of the encode from which analysis info has to be re-used
>> ( set to 'nil'
>> +       if analysis reuse isn't preferred ), and reuse-level indicates
>> the level ( :option:`--analysis-load-reuse-level`)
>> +       at which analysis info has to be reused.
>> +
>> +       A sample config file is available in `the downloads page <
>> https://bitbucket.org/multicoreware/x265/downloads/Sample_ABR_ladder_config
>> >`_
>> +
>> +       Default: Disabled ( Conventional single encode generation ).
>> Experimental feature.
>> +
>> +       **CLI ONLY**
>> +
>>
>>  SVT-HEVC Encoder Options
>>  ========================
>> diff -r 3eccfeafc040 -r d78121f6445e source/x265.cpp
>> --- a/source/x265.cpp   Wed Feb 26 16:37:13 2020 +0530
>> +++ b/source/x265.cpp   Tue Mar 31 16:43:30 2020 +0530
>> @@ -27,6 +27,7 @@
>>
>>  #include "x265.h"
>>  #include "x265cli.h"
>> +#include "abrEncApp.h"
>>
>>  #include "input/input.h"
>>  #include "output/output.h"
>>
> [KS] Check if all included headers in x265.cpp are required. For instance
> svt.h  is no longer required here.
>
[AM] Yes, some of the headers are no longer required here. I'll remove
them.

> @@ -49,12 +50,13 @@
>>
>>  using namespace X265_NS;
>>
>> +#ifdef _WIN32
>> +#define strdup _strdup
>> +#endif
>> +
>>  /* Ctrl-C handler */
>>  static volatile sig_atomic_t b_ctrl_c /* = 0 */;
>> -static void sigint_handler(int)
>> -{
>> -    b_ctrl_c = 1;
>> -}
>> +
>>  #define START_CODE 0x00000001
>>  #define START_CODE_BYTES 4
>>
> [KS] Same for macros as well. Double check.
>
[AM] Sure, I'll double-check and remove the unwanted macros as well.

>
>> @@ -91,59 +93,178 @@
>>  }
>>  #endif
>>
>> -/* Parse the RPU file and extract the RPU corresponding to the current
>> picture
>> - * and fill the rpu field of the input picture */
>> -static int rpuParser(x265_picture * pic, FILE * ptr)
>> -{
>> -    uint8_t byteVal;
>> -    uint32_t code = 0;
>> -    int bytesRead = 0;
>> -    pic->rpu.payloadSize = 0;
>> +/* Checks for abr-ladder config file in the command line.
>> + * Returns true if abr-config file is present. Returns
>> + * false otherwise */
>>
>> -    if (!pic->pts)
>> -    {
>> -        while (bytesRead++ < 4 && fread(&byteVal, sizeof(uint8_t), 1,
>> ptr))
>> -            code = (code << 8) | byteVal;
>> -
>> -        if (code != START_CODE)
>> -        {
>> -            x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU
>> startcode in POC %d\n", pic->pts);
>> -            return 1;
>> -        }
>> -    }
>> -
>> -    bytesRead = 0;
>> -    while (fread(&byteVal, sizeof(uint8_t), 1, ptr))
>> +static bool IsAbrLadder(int argc, char **argv, FILE **abrConfig)
>> +{
>> +    for (optind = 0;;)
>>      {
>> -        code = (code << 8) | byteVal;
>> -        if (bytesRead++ < 3)
>> -            continue;
>> -        if (bytesRead >= 1024)
>> +        int long_options_index = -1;
>> +        int c = getopt_long(argc, argv, short_options, long_options,
>> &long_options_index);
>> +        if (c == -1)
>> +            break;
>> +        if (long_options_index < 0 && c > 0)
>>          {
>> -            x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU
>> size in POC %d\n", pic->pts);
>> -            return 1;
>> +            for (size_t i = 0; i < sizeof(long_options) /
>> sizeof(long_options[0]); i++)
>> +            {
>> +                if (long_options[i].val == c)
>> +                {
>> +                    long_options_index = (int)i;
>> +                    break;
>> +                }
>> +            }
>> +
>> +            if (long_options_index < 0)
>> +            {
>> +                /* getopt_long might have already printed an error
>> message */
>> +                if (c != 63)
>> +                    x265_log(NULL, X265_LOG_WARNING, "internal error:
>> short option '%c' has no long option\n", c);
>> +                return false;
>> +            }
>>          }
>> -
>> -        if (code != START_CODE)
>> -            pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8))
>> & 0xFF;
>> -        else
>> -            return 0;
>> +        if (long_options_index < 0)
>> +        {
>> +            x265_log(NULL, X265_LOG_WARNING, "short option '%c'
>> unrecognized\n", c);
>> +            return false;
>> +        }
>> +        if (!strcmp(long_options[long_options_index].name, "abr-ladder"))
>> +        {
>> +            *abrConfig = x265_fopen(optarg, "rb");
>> +            if (!abrConfig)
>> +                x265_log_file(NULL, X265_LOG_ERROR, "%s abr-ladder
>> config file not found or error in opening zone file\n", optarg);
>> +            return true;
>> +        }
>>      }
>> +    return false;
>> +}
>>
> [KS] Do we need a separate parsing just to search for abrLadder option
> in command? Can this go to cliopt parse ?
>
[AM] The --abr-ladder config file has CLI headers in addition to the CLI
for each tier in the ABR ladder. To read the file, I have introduced a
separate module that parses the CLI header first and then calls the cliopt
parse. The application will take one of the 2 flows ( 1. cliopt parse for
single encode case and 2. File parse for --abr-ladder case ) based on this
option. Hence I have introduced this module.
This numEncodes count is also required in advance to initialize cliopt
structure.


>
>> -    int ShiftBytes = START_CODE_BYTES - (bytesRead -
>> pic->rpu.payloadSize);
>> -    int bytesLeft = bytesRead - pic->rpu.payloadSize;
>> -    code = (code << ShiftBytes * 8);
>> -    for (int i = 0; i < bytesLeft; i++)
>> +static uint8_t getNumAbrEncodes(FILE* abrConfig)
>> +{
>> +    char line[1024];
>> +    uint8_t numEncodes = 0;
>> +
>> +    while (fgets(line, sizeof(line), abrConfig))
>>      {
>> -        pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) &
>> 0xFF;
>> -        code = (code << 8);
>> +        if (strcmp(line, "\n") == 0)
>> +            continue;
>> +        else if (!(*line == '#'))
>> +            numEncodes++;
>>      }
>> -    if (!pic->rpu.payloadSize)
>> -        x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU not found for
>> POC %d\n", pic->pts);
>> -    return 0;
>> +    rewind(abrConfig);
>> +    return numEncodes;
>>  }
>>
>> +#define X265_HEAD_ENTRIES 3
>>
> [KS] Can we move all #define to the start of the file(for code
> consistency)?
>
[AM] Okay, will do.

>
>> +static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[])
>> +{
>> +    char line[1024];
>> +    char* argLine;
>> +    uint32_t numEncodes = 0;
>> +
>> +    while (fgets(line, sizeof(line), abrConfig))
>> +    {
>> +        if (!((*line == '#') || (strcmp(line, "\r\n") == 0)))
>> +            numEncodes++;
>> +    }
>> +    rewind(abrConfig);
>> +
>>
> [KS] Why are we computing numEncodes again? When it is already computed in
> the getNumEncode() invoked from main
>
[AM] Yes, this is redundant. I'll add it to the argument list.

>
>
>> +    for (uint32_t i = 0; i < numEncodes; i++)
>> +    {
>> +        while (fgets(line, sizeof(line), abrConfig))
>> +        {
>> +            if (*line == '#' || (strcmp(line, "\r\n") == 0))
>> +                continue;
>> +            int index = (int)strcspn(line, "\r\n");
>> +            line[index] = '\0';
>> +            argLine = line;
>> +            char* start = strchr(argLine, ' ');
>> +            while (isspace((unsigned char)*start)) start++;
>> +            int argCount = 0;
>> +            char **args = (char**)malloc(256 * sizeof(char *));
>> +            // Adding a dummy string to avoid file parsing error
>> +            args[argCount++] = (char *)"x265";
>>
> [KS] Can you explain what you are doing here?
>
[AM] cliopt parse will ignore the first argument in the argv list ( the exe
arg ) . Hence adding this dummy argument so that none of the valid
arguments will get dropped.

> +
>> +            /* Parse CLI header to identify the ID of the load encode
>> and the reuse level */
>> +            char *header = strtok(argLine, "[]");
>> +            uint32_t idCount = 0;
>> +            char *id = strtok(header, ":");
>> +            char *head[X265_HEAD_ENTRIES];
>> +            cliopt[i].encId = i;
>> +
>> +            while (id && (idCount <= X265_HEAD_ENTRIES))
>> +            {
>> +                head[idCount] = id;
>> +                id = strtok(NULL, ":");
>> +                idCount++;
>> +            }
>> +            if (idCount != X265_HEAD_ENTRIES)
>> +            {
>> +                x265_log(NULL, X265_LOG_ERROR, "Incorrect number of
>> arguments in ABR CLI header at line %d\n", i);
>> +                return false;
>> +            }
>> +            else
>> +            {
>> +                cliopt[i].encName = strdup(head[0]);
>> +                cliopt[i].loadLevel = atoi(head[1]);
>> +                cliopt[i].reuseName = strdup(head[2]);
>> +            }
>> +
>> +            char* token = strtok(start, " ");
>> +            while (token)
>> +            {
>> +                args[argCount++] = token;
>> +                token = strtok(NULL, " ");
>> +            }
>>
> [KS] Are there any string manipulation lib APIs that count words so that
> we can avoid this loop
>
[AM] We have to populate args with the tokens as well. I don't find any lib
that does both.

> +            args[argCount] = NULL;
>> +            if (cliopt[i].parse(argCount, args))
>> +            {
>> +                cliopt[i].destroy();
>> +                if (cliopt[i].api)
>> +                    cliopt[i].api->param_free(cliopt[i].param);
>> +                exit(1);
>> +            }
>> +            break;
>> +        }
>> +    }
>> +    return true;
>> +}
>> +
>> +static bool setRefContext(CLIOptions cliopt[], uint32_t numEncodes)
>> +{
>> +    bool hasRef = false;
>> +    bool isRefFound = false;
>> +
>> +    /* Identify reference encode IDs and set save/load reuse levels */
>> +    for (uint32_t curEnc = 0; curEnc < numEncodes; curEnc++)
>> +    {
>> +        isRefFound = false;
>> +        hasRef = !strcmp(cliopt[curEnc].reuseName, "nil") ? false : true;
>> +        if (hasRef)
>> +        {
>> +            for (uint32_t refEnc = 0; refEnc < numEncodes; refEnc++)
>> +            {
>> +                if (!strcmp(cliopt[curEnc].reuseName,
>> cliopt[refEnc].encName))
>> +                {
>> +                    cliopt[curEnc].refId = refEnc;
>> +                    cliopt[refEnc].numRefs++;
>> +                    cliopt[refEnc].saveLevel =
>> X265_MAX(cliopt[refEnc].saveLevel, cliopt[curEnc].loadLevel);
>> +                    isRefFound = true;
>> +                    break;
>> +                }
>> +            }
>> +            if (!isRefFound)
>> +            {
>> +                x265_log(NULL, X265_LOG_ERROR, "Reference encode (%s)
>> not found for %s\n", cliopt[curEnc].reuseName,
>> +                    cliopt[curEnc].encName);
>> +                return false;
>> +            }
>> +        }
>> +    }
>> +    return true;
>> +}
>>  /* CLI return codes:
>>   *
>>   * 0 - encode successful
>>
> [KS] Are these CLI codes still valid?
>
[AM] This is handled in the subsequent patch.

>
>
>> @@ -168,354 +289,42 @@
>>      get_argv_utf8(&argc, &argv);
>>  #endif
>>
>> -    ReconPlay* reconPlay = NULL;
>> -    CLIOptions cliopt;
>> +    uint8_t numEncodes = 1;
>> +    FILE *abrConfig = NULL;
>> +    bool isAbrLadder = IsAbrLadder(argc, argv, &abrConfig);
>>
> [KS] Function naming convention. If there is conflict with variable name,
> can we change the function name ?
>
[AM] Will change the function name.

> +
>> +    if (isAbrLadder)
>> +        numEncodes = getNumAbrEncodes(abrConfig);
>> +
>> +    CLIOptions* cliopt = new CLIOptions[numEncodes];
>>
>> -    if (cliopt.parse(argc, argv))
>> +    if (isAbrLadder)
>>      {
>> -        cliopt.destroy();
>> -        if (cliopt.api)
>> -            cliopt.api->param_free(cliopt.param);
>> +        if(!parseAbrConfig(abrConfig, cliopt))
>>
> [KS]Space
>
[AM] will fix.

> +            exit(1);
>> +        if(!setRefContext(cliopt, numEncodes))
>>
> [KS]Space
>
[AM] will fix.

>
>
>> +            exit(1);
>> +    }
>> +    else if(cliopt[0].parse(argc, argv))
>>
> [KS]Space
>
[AM] will fix.

>
>
>> +    {
>> +        cliopt[0].destroy();
>> +        if (cliopt[0].api)
>> +            cliopt[0].api->param_free(cliopt[0].param);
>>          exit(1);
>>      }
>>
>> -    x265_param* param = cliopt.param;
>> -    const x265_api* api = cliopt.api;
>> -#if ENABLE_LIBVMAF
>> -    x265_vmaf_data* vmafdata = cliopt.vmafData;
>> -#endif
>> -    /* This allows muxers to modify bitstream format */
>> -    cliopt.output->setParam(param);
>> -
>> -    if (cliopt.reconPlayCmd)
>> -        reconPlay = new ReconPlay(cliopt.reconPlayCmd, *param);
>> -
>> -    if (cliopt.zoneFile)
>> -    {
>> -        if (!cliopt.parseZoneFile())
>> -        {
>> -            x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile\n");
>> -            fclose(cliopt.zoneFile);
>> -            cliopt.zoneFile = NULL;
>> -        }
>> -    }
>> -
>> -    /* note: we could try to acquire a different libx265 API here based
>> on
>> -     * the profile found during option parsing, but it must be done
>> before
>> -     * opening an encoder */
>> -
>> -    x265_encoder *encoder = api->encoder_open(param);
>> -    if (!encoder)
>> -    {
>> -        x265_log(param, X265_LOG_ERROR, "failed to open encoder\n");
>> -        cliopt.destroy();
>> -        api->param_free(param);
>> -        api->cleanup();
>> -        exit(2);
>> -    }
>> -
>> -    /* get the encoder parameters post-initialization */
>> -    api->encoder_parameters(encoder, param);
>> -
>> -     /* Control-C handler */
>> -    if (signal(SIGINT, sigint_handler) == SIG_ERR)
>> -        x265_log(param, X265_LOG_ERROR, "Unable to register CTRL+C
>> handler: %s\n", strerror(errno));
>> +    int ret = 0;
>>
> [KS] Ret is unmodified. Do we need it?
>
[AM] Handled in the subsequent patch.

>
>> -    x265_picture pic_orig, pic_out;
>> -    x265_picture *pic_in = &pic_orig;
>> -    /* Allocate recon picture if analysis save/load is enabled */
>> -    std::priority_queue<int64_t>* pts_queue = cliopt.output->needPTS() ?
>> new std::priority_queue<int64_t>() : NULL;
>> -    x265_picture *pic_recon = (cliopt.recon || param->analysisSave ||
>> param->analysisLoad || pts_queue || reconPlay || param->csvLogLevel) ?
>> &pic_out : NULL;
>> -    uint32_t inFrameCount = 0;
>> -    uint32_t outFrameCount = 0;
>> -    x265_nal *p_nal;
>> -    x265_stats stats;
>> -    uint32_t nal;
>> -    int16_t *errorBuf = NULL;
>> -    bool bDolbyVisionRPU = false;
>> -    uint8_t *rpuPayload = NULL;
>> -    int ret = 0;
>> -    int inputPicNum = 1;
>> -    x265_picture picField1, picField2;
>> -
>> -    if (!param->bRepeatHeaders && !param->bEnableSvtHevc)
>> +    AbrEncoder* abrEnc = new AbrEncoder(cliopt, numEncodes, ret);
>> +    int threadsActive = abrEnc->m_numActiveEncodes.get();
>> +    while (threadsActive)
>>      {
>> -        if (api->encoder_headers(encoder, &p_nal, &nal) < 0)
>> -        {
>> -            x265_log(param, X265_LOG_ERROR, "Failure generating stream
>> headers\n");
>> -            ret = 3;
>> -            goto fail;
>> -        }
>> -        else
>> -            cliopt.totalbytes += cliopt.output->writeHeaders(p_nal, nal);
>> -    }
>> -
>> -    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)
>> -    {
>> -        rpuPayload = X265_MALLOC(uint8_t, 1024);
>> -        pic_in->rpu.payload = rpuPayload;
>> -        if (pic_in->rpu.payload)
>> -            bDolbyVisionRPU = true;
>> -    }
>> -
>> -    if (cliopt.bDither)
>> -    {
>> -        errorBuf = X265_MALLOC(int16_t, param->sourceWidth + 1);
>> -        if (errorBuf)
>> -            memset(errorBuf, 0, (param->sourceWidth + 1) *
>> sizeof(int16_t));
>> -        else
>> -            cliopt.bDither = false;
>> +        threadsActive =
>> abrEnc->m_numActiveEncodes.waitForChange(threadsActive);
>>      }
>>
>> -    // main encoder loop
>> -    while (pic_in && !b_ctrl_c)
>> -    {
>> -        pic_orig.poc = (param->bField && param->interlaceMode) ?
>> inFrameCount * 2 : inFrameCount;
>> -        if (cliopt.qpfile)
>> -        {
>> -            if (!cliopt.parseQPFile(pic_orig))
>> -            {
>> -                x265_log(NULL, X265_LOG_ERROR, "can't parse qpfile for
>> frame %d\n", pic_in->poc);
>> -                fclose(cliopt.qpfile);
>> -                cliopt.qpfile = NULL;
>> -            }
>> -        }
>> -
>> -        if (cliopt.framesToBeEncoded && inFrameCount >=
>> cliopt.framesToBeEncoded)
>> -            pic_in = NULL;
>> -        else if (cliopt.input->readPicture(pic_orig))
>> -            inFrameCount++;
>> -        else
>> -            pic_in = NULL;
>> -
>> -        if (pic_in)
>> -        {
>> -            if (pic_in->bitDepth > param->internalBitDepth &&
>> cliopt.bDither)
>> -            {
>> -                x265_dither_image(pic_in, cliopt.input->getWidth(),
>> cliopt.input->getHeight(), errorBuf, param->internalBitDepth);
>> -                pic_in->bitDepth = param->internalBitDepth;
>> -            }
>> -            /* 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;
>> -
>> -                    size_t fieldFrameSize = (size_t)pic_in->framesize >>
>> 1;
>> -                    char* field1Buf = X265_MALLOC(char, fieldFrameSize);
>> -                    char* field2Buf = X265_MALLOC(char, fieldFrameSize);
>> -
>> -                    int stride = picField1.stride[0] =
>> picField2.stride[0] = pic_in->stride[0];
>> -                    uint64_t 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 (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;
>> -                }
>> -            }
>> -        }
>> -
>> -        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 );
>> -        }
>> -    }
>> -
>> -    /* Flush the encoder */
>> -    while (!b_ctrl_c)
>> -    {
>> -        int numEncoded = api->encoder_encode(encoder, &p_nal, &nal,
>> NULL, pic_recon);
>> -        if (numEncoded < 0)
>> -        {
>> -            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 (!numEncoded)
>> -            break;
>> -    }
>> -
>> -    if (bDolbyVisionRPU)
>> -    {
>> -        if(fgetc(cliopt.dolbyVisionRpu) != EOF)
>> -            x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU count is
>> greater than frame count\n");
>> -        x265_log(NULL, X265_LOG_INFO, "VES muxing with Dolby Vision RPU
>> file successful\n");
>> -    }
>> -
>> -    /* clear progress report */
>> -    if (cliopt.bProgress)
>> -        fprintf(stderr, "%*s\r", 80, " ");
>> -
>> -fail:
>> -
>> -    delete reconPlay;
>> -
>> -    api->encoder_get_stats(encoder, &stats, sizeof(stats));
>> -    if (param->csvfn && !b_ctrl_c)
>> -#if ENABLE_LIBVMAF
>> -        api->vmaf_encoder_log(encoder, argc, argv, param, vmafdata);
>> -#else
>> -        api->encoder_log(encoder, argc, argv);
>> -#endif
>> -    api->encoder_close(encoder);
>> -
>> -    int64_t second_largest_pts = 0;
>> -    int64_t largest_pts = 0;
>> -    if (pts_queue && pts_queue->size() >= 2)
>> -    {
>> -        second_largest_pts = -pts_queue->top();
>> -        pts_queue->pop();
>> -        largest_pts = -pts_queue->top();
>> -        pts_queue->pop();
>> -        delete pts_queue;
>> -        pts_queue = NULL;
>> -    }
>> -    cliopt.output->closeFile(largest_pts, second_largest_pts);
>> -
>> -    if (b_ctrl_c)
>> -        general_log(param, NULL, X265_LOG_INFO, "aborted at input frame
>> %d, output frame %d\n",
>> -                    cliopt.seek + inFrameCount,
>> stats.encodedPictureCount);
>> -
>> -    api->cleanup(); /* Free library singletons */
>> -
>> -    cliopt.destroy();
>> -
>> -    api->param_free(param);
>> -
>> -    X265_FREE(errorBuf);
>> -    X265_FREE(rpuPayload);
>> +    abrEnc->destroy();
>> +    for (uint8_t idx = 0; idx < numEncodes; idx++)
>> +        cliopt[idx].destroy();
>>
>>      SetConsoleTitle(orgConsoleTitle);
>>      SetThreadExecutionState(ES_CONTINUOUS);
>> diff -r 3eccfeafc040 -r d78121f6445e source/x265cli.cpp
>> --- a/source/x265cli.cpp        Wed Feb 26 16:37:13 2020 +0530
>> +++ b/source/x265cli.cpp        Tue Mar 31 16:43:30 2020 +0530
>> @@ -348,6 +348,8 @@
>>          H0("   --svt-pred-struct             Select pred structure for
>> SVT HEVC encoder;  Accepts inputs in the range 0-2 \n");
>>          H0("   --[no-]svt-fps-in-vps         Enable VPS timing info for
>> SVT HEVC encoder  \n");
>>  #endif
>> +        H0(" ABR-ladder settings\n");
>> +        H0("   --abr-ladder <file>           File containing config
>> settings required for the generation of ABR-ladder\n");
>>          H1("\nExecutable return codes:\n");
>>          H1("    0 - encode successful\n");
>>          H1("    1 - unable to parse command line\n");
>> diff -r 3eccfeafc040 -r d78121f6445e source/x265cli.h
>> --- a/source/x265cli.h  Wed Feb 26 16:37:13 2020 +0530
>> +++ b/source/x265cli.h  Tue Mar 31 16:43:30 2020 +0530
>> @@ -372,6 +372,7 @@
>>      { "cll", no_argument, NULL, 0 },
>>      { "no-cll", no_argument, NULL, 0 },
>>      { "hme-range", required_argument, NULL, 0 },
>> +    { "abr-ladder", required_argument, NULL, 0 },
>>      { 0, 0, 0, 0 },
>>      { 0, 0, 0, 0 },
>>      { 0, 0, 0, 0 },
>> @@ -399,6 +400,18 @@
>>          uint64_t totalbytes;
>>          int64_t startTime;
>>          int64_t prevUpdateTime;
>> +
>> +        /* ABR ladder settings */
>> +        bool enableScaler;
>> +        char*    encName;
>> +        char*    reuseName;
>> +        uint32_t encId;
>> +        int      refId;
>> +        uint32_t loadLevel;
>> +        uint32_t saveLevel;
>> +        uint32_t numRefs;
>> +
>> +
>>          /* in microseconds */
>>          static const int UPDATE_INTERVAL = 250000;
>>          CLIOptions()
>> @@ -420,6 +433,12 @@
>>              startTime = x265_mdate();
>>              prevUpdateTime = 0;
>>              bDither = false;
>> +            enableScaler = false;
>> +            encId = 0;
>> +            refId = -1;
>> +            loadLevel = 0;
>> +            saveLevel = 0;
>> +            numRefs = 0;
>>          }
>>
>>          void destroy();
>> _______________________________________________
>> x265-devel mailing list
>> x265-devel at videolan.org
>> https://mailman.videolan.org/listinfo/x265-devel
>>
>
>
> --
> Regards,
> Kavitha
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>


-- 
Regards,
*Aruna Matheswaran,*
Video Codec Engineer,
Media & AI analytics BU,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200413/42a9a08b/attachment-0001.html>


More information about the x265-devel mailing list