On Tue, Mar 31, 2020 at 6:22 PM Aruna Matheswaran < ar...@multicorewareinc.com> wrote:
> # HG changeset patch > # User Aruna Matheswaran <ar...@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. > @@ -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. > > @@ -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 ? > > - 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)? > > +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 > + 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? > + > + /* 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 > + 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? > @@ -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 ? > + > + 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 > + exit(1); > + if(!setRefContext(cliopt, numEncodes)) > [KS]Space > + exit(1); > + } > + else if(cliopt[0].parse(argc, argv)) > [KS]Space > + { > + 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? > > - 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@videolan.org > https://mailman.videolan.org/listinfo/x265-devel > -- Regards, Kavitha
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel