<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 31, 2020 at 6:22 PM Aruna Matheswaran <<a href="mailto:aruna@multicorewareinc.com" target="_blank">aruna@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 Aruna Matheswaran <<a href="mailto:aruna@multicorewareinc.com" target="_blank">aruna@multicorewareinc.com</a>><br>
# Date 1582715233 -19800<br>
#      Wed Feb 26 16:37:13 2020 +0530<br>
# Node ID 3eccfeafc04000b68c25ab52c43741a1acac21c8<br>
# Parent  7ebf4b9369b3037370a73be24f5f1bd93cce7822<br>
app: Add definitions for ABR (Adaptive Bit-Rate) encoding<br>
<br>
diff -r 7ebf4b9369b3 -r 3eccfeafc040 source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt     Wed Feb 26 14:40:35 2020 +0530<br>
+++ b/source/CMakeLists.txt     Wed Feb 26 16:37:13 2020 +0530<br>
@@ -745,16 +745,16 @@<br>
         # Xcode seems unable to link the CLI with libs, so link as one targget<br>
         if(ENABLE_HDR10_PLUS)<br>
         add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT}<br>
-                        x265.cpp x265.h x265cli.cpp x265cli.h<br>
+                        x265.cpp x265.h x265cli.cpp x265cli.h abrEncApp.cpp abrEncApp.h<br>
                         $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> $<TARGET_OBJECTS:dynamicHDR10> ${ASM_OBJS})<br>
         else()<br>
             add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT}<br>
-                        x265.cpp x265.h x265cli.cpp x265cli.h<br>
+                        x265.cpp x265.h x265cli.cpp x265cli.h abrEncApp.cpp abrEncApp.h<br>
                         $<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${ASM_OBJS})<br>
         endif()<br>
     else()<br>
         add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT} ${X265_RC_FILE}<br>
-                       ${ExportDefs} x265.cpp x265.h x265cli.cpp x265cli.h)<br>
+                       ${ExportDefs} x265.cpp x265.h x265cli.cpp x265cli.h abrEncApp.cpp abrEncApp.h)<br>
         if(WIN32 OR NOT ENABLE_SHARED OR INTEL_CXX)<br>
             # The CLI cannot link to the shared library on Windows, it<br>
             # requires internal APIs not exported from the DLL<br>
diff -r 7ebf4b9369b3 -r 3eccfeafc040 source/abrEncApp.cpp<br>
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000<br>
+++ b/source/abrEncApp.cpp      Wed Feb 26 16:37:13 2020 +0530<br>
@@ -0,0 +1,1150 @@<br>
+/*****************************************************************************<br>
+* Copyright (C) 2013-2020 MulticoreWare, Inc<br>
+*<br>
+* Authors: Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com" target="_blank">pooja@multicorewareinc.com</a>><br>
+*          Aruna Matheswaran <<a href="mailto:aruna@multicorewareinc.com" target="_blank">aruna@multicorewareinc.com</a>><br>
+*<br>
+* This program is free software; you can redistribute it and/or modify<br>
+* it under the terms of the GNU General Public License as published by<br>
+* the Free Software Foundation; either version 2 of the License, or<br>
+* (at your option) any later version.<br>
+*<br>
+* This program is distributed in the hope that it will be useful,<br>
+* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
+* GNU General Public License for more details.<br>
+*<br>
+* You should have received a copy of the GNU General Public License<br>
+* along with this program; if not, write to the Free Software<br>
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.<br>
+*<br>
+* This program is also available under a commercial proprietary license.<br>
+* For more information, contact us at license @ <a href="http://x265.com" rel="noreferrer" target="_blank">x265.com</a>.<br>
+*****************************************************************************/<br>
+<br>
+#include "abrEncApp.h"<br>
+#include "mv.h"<br>
+#include "slice.h"<br>
+#include "param.h"<br>
+<br>
+#include <signal.h><br>
+#include <errno.h><br>
+<br>
+#include <queue><br>
+<br>
+using namespace X265_NS;<br>
+<br>
+/* Ctrl-C handler */<br>
+static volatile sig_atomic_t b_ctrl_c /* = 0 */;<br>
+static void sigint_handler(int)<br>
+{<br>
+    b_ctrl_c = 1;<br>
+}<br>
+<br>
+#define START_CODE 0x00000001<br>
+#define START_CODE_BYTES 4<br>
+<br>
+/* Parse the RPU file and extract the RPU corresponding to the current picture<br>
+* and fill the rpu field of the input picture */<br>
+static int rpuParser(x265_picture * pic, FILE * ptr)<br>
+{<br>
+    uint8_t byteVal;<br>
+    uint32_t code = 0;<br>
+    int bytesRead = 0;<br>
+    pic->rpu.payloadSize = 0;<br>
+<br>
+    if (!pic->pts)<br>
+    {<br>
+        while (bytesRead++ < 4 && fread(&byteVal, sizeof(uint8_t), 1, ptr))<br>
+            code = (code << 8) | byteVal;<br>
+<br>
+        if (code != START_CODE)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU startcode in POC %d\n", pic->pts);<br>
+            return 1;<br>
+        }<br>
+    }<br>
+<br>
+    bytesRead = 0;<br>
+    while (fread(&byteVal, sizeof(uint8_t), 1, ptr))<br>
+    {<br>
+        code = (code << 8) | byteVal;<br>
+        if (bytesRead++ < 3)<br>
+            continue;<br>
+        if (bytesRead >= 1024)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU size in POC %d\n", pic->pts);<br>
+            return 1;<br>
+        }<br>
+<br>
+        if (code != START_CODE)<br>
+            pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;<br>
+        else<br>
+            return 0;<br>
+    }<br>
+<br>
+    int ShiftBytes = START_CODE_BYTES - (bytesRead - pic->rpu.payloadSize);<br>
+    int bytesLeft = bytesRead - pic->rpu.payloadSize;<br>
+    code = (code << ShiftBytes * 8);<br>
+    for (int i = 0; i < bytesLeft; i++)<br>
+    {<br>
+        pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;<br>
+        code = (code << 8);<br>
+    }<br>
+    if (!pic->rpu.payloadSize)<br>
+        x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU not found for POC %d\n", pic->pts);<br>
+    return 0;<br>
+}<br></blockquote><div>[KS] I see that parsing of most of CLI specified files happen are defined in CLIOptions except RPU parsing of dolby? Is there any reason?</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+<br>
+namespace X265_NS {<br>
+    // private namespace<br>
+#define X265_INPUT_QUEUE_SIZE 250<br>
+<br>
+    AbrEncoder::AbrEncoder(CLIOptions cliopt[], uint8_t numEncodes, int &ret)<br>
+    {<br>
+        m_numEncodes = numEncodes;<br>
+        m_numActiveEncodes.set(numEncodes);<br>
+        m_queueSize = X265_INPUT_QUEUE_SIZE;<br></blockquote><div> [KS] If queueSize is constant, is it necessary to define it as an ABrEncoder member?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        m_passEnc = X265_MALLOC(PassEncoder*, m_numEncodes);<br>
+<br>
+        for (uint8_t i = 0; i < m_numEncodes; i++)<br>
+        {<br>
+            m_passEnc[i] = new PassEncoder(i, cliopt[i], this);<br>
+            if (!m_passEnc[i])<br>
+            {<br>
+                x265_log(NULL, X265_LOG_ERROR, "Unable to allocate memory for passEncoder\n");<br>
+                ret = 4;<br>
+            }<br>
+            m_passEnc[i]->init(ret);<br>
+        }<br>
+<br>
+        if (!allocBuffers())<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "Unable to allocate memory for buffers\n");<br>
+            ret = 4;<br>
+        }<br></blockquote><div>[KS] Sorry for not noticing that ret defined in main is reset here. Please ignore my previous comment.  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+        /* start passEncoder worker threads */<br>
+        for (uint8_t pass = 0; pass < m_numEncodes; pass++)<br>
+            m_passEnc[pass]->startThreads();<br>
+    }<br>
+<br>
+    bool AbrEncoder::allocBuffers()<br>
+    {<br>
+        m_inputPicBuffer = X265_MALLOC(x265_picture**, m_numEncodes);<br>
+        m_analysisBuffer = X265_MALLOC(x265_analysis_data*, m_numEncodes);<br>
+<br>
+        m_picWriteCnt = new ThreadSafeInteger[m_numEncodes];<br>
+        m_picReadCnt = new ThreadSafeInteger[m_numEncodes];<br>
+        m_analysisWriteCnt = new ThreadSafeInteger[m_numEncodes];<br>
+        m_analysisReadCnt = new ThreadSafeInteger[m_numEncodes];<br>
+<br>
+        m_picIdxReadCnt = X265_MALLOC(ThreadSafeInteger*, m_numEncodes);<br>
+        m_analysisWrite = X265_MALLOC(ThreadSafeInteger*, m_numEncodes);<br>
+        m_analysisRead = X265_MALLOC(ThreadSafeInteger*, m_numEncodes);<br>
+        m_readFlag = X265_MALLOC(int*, m_numEncodes);<br>
+<br>
+        for (uint8_t pass = 0; pass < m_numEncodes; pass++)<br>
+        {<br>
+            m_inputPicBuffer[pass] = X265_MALLOC(x265_picture*, m_queueSize);<br>
+            for (uint32_t idx = 0; idx < m_queueSize; idx++)<br>
+            {<br>
+                m_inputPicBuffer[pass][idx] = NULL;<br>
+            }<br>
+            m_analysisBuffer[pass] = X265_MALLOC(x265_analysis_data, m_queueSize);<br>
+            m_picIdxReadCnt[pass] = new ThreadSafeInteger[m_queueSize];<br>
+            m_analysisWrite[pass] = new ThreadSafeInteger[m_queueSize];<br>
+            m_analysisRead[pass] = new ThreadSafeInteger[m_queueSize];<br>
+            m_readFlag[pass] = X265_MALLOC(int, m_queueSize);<br>
+        }<br>
+        return true;<br>
+    }<br>
+<br>
+    void AbrEncoder::closeEncoder()<br>
+    {<br>
+        for (uint8_t pidx = 0; pidx < m_numEncodes; pidx++)<br>
+        {<br>
+            PassEncoder *passWorker = m_passEnc[pidx];<br>
+            if (passWorker)<br>
+                passWorker->close();<br>
+        }<br>
+    }<br>
+<br>
+    void AbrEncoder::destroy()<br>
+    {<br>
+        closeEncoder();<br>
+        x265_cleanup(); /* Free library singletons */<br>
+        for (uint8_t pass = 0; pass < m_numEncodes; pass++)<br>
+        {<br>
+            for (uint32_t index = 0; index < m_queueSize; index++)<br>
+            {<br>
+                x265_picture_free(m_inputPicBuffer[pass][index]);<br>
+            }<br>
+            X265_FREE(m_inputPicBuffer[pass]);<br>
+            X265_FREE(m_analysisBuffer[pass]);<br>
+            delete[] m_picIdxReadCnt[pass];<br>
+            delete[] m_analysisWrite[pass];<br>
+            delete[] m_analysisRead[pass];<br>
+            m_passEnc[pass]->destroy();<br>
+        }<br>
+        X265_FREE(m_inputPicBuffer);<br>
+        X265_FREE(m_analysisBuffer);<br>
+        X265_FREE(m_readFlag);<br>
+<br>
+        delete[] m_picWriteCnt;<br>
+        delete[] m_picReadCnt;<br>
+        delete[] m_analysisWriteCnt;<br>
+        delete[] m_analysisReadCnt;<br>
+<br>
+        X265_FREE(m_picIdxReadCnt);<br>
+        X265_FREE(m_analysisWrite);<br>
+        X265_FREE(m_analysisRead);<br>
+<br>
+        X265_FREE(m_passEnc);<br>
+    }<br>
+<br>
+    PassEncoder::PassEncoder(uint32_t id, CLIOptions cliopt, AbrEncoder *parent)<br>
+    {<br>
+        m_id = id;<br>
+        m_cliopt = cliopt;<br>
+        m_parent = parent;<br>
+        if(!(m_cliopt.enableScaler && m_id))<br>
+            m_input = m_cliopt.input;<br>
+        m_param = x265_param_alloc();<br>
+        x265_copy_params(m_param, cliopt.param);<br></blockquote><div>[KS] Is this param alloc/copy essential? Do you foresee problems in just pointing it to cliopt.param? </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        m_doneReading = false;<br>
+        m_lastIdx = -1;<br>
+        m_encoder = NULL;<br>
+        m_scaler = NULL;<br>
+        m_reader = NULL;<br>
+    }<br>
+<br>
+    int PassEncoder::init(int &result)<br>
+    {<br>
+        if (m_parent->m_numEncodes > 1)<br>
+            setReuseLevel();<br>
+                <br>
+        if (!(m_cliopt.enableScaler && m_id))<br>
+            m_reader = new Reader(m_id, this);<br>
+        else<br>
+        {<br>
+            VideoDesc *src = NULL, *dst = NULL;<br>
+            dst = new VideoDesc(m_param->sourceWidth, m_param->sourceHeight, m_param->internalCsp, m_param->internalBitDepth);<br>
+            int dstW = m_parent->m_passEnc[m_id - 1]->m_param->sourceWidth;<br>
+            int dstH = m_parent->m_passEnc[m_id - 1]->m_param->sourceHeight;<br>
+            src = new VideoDesc(dstW, dstH, m_param->internalCsp, m_param->internalBitDepth);<br>
+            if (src != NULL && dst != NULL)<br>
+            {<br>
+                m_scaler = new Scaler(0, 1, m_id, src, dst, this);<br>
+                if (!m_scaler)<br>
+                {<br>
+                    x265_log(m_param, X265_LOG_ERROR, "\n MALLOC failure in Scaler");<br>
+                    result = 4;<br>
+                }<br>
+            }<br>
+        }<br>
+<br>
+        if (m_cliopt.zoneFile)<br>
+        {<br>
+            if (!m_cliopt.parseZoneFile())<br>
+            {<br>
+                x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile\n");<br>
+                fclose(m_cliopt.zoneFile);<br>
+                m_cliopt.zoneFile = NULL;<br>
+            }<br>
+        }<br>
+<br>
+        if (m_param)<br>
+            m_encoder = x265_encoder_open(m_param);<br>
+        if (!m_encoder)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "x265_encoder_open() failed for Enc, \n");<br>
+            return -1;<br>
+        }<br>
+        x265_encoder_parameters(m_encoder, m_param);<br>
+        return 1;<br>
+    }<br>
+<br>
+    void PassEncoder::setReuseLevel()<br>
+    {<br>
+        uint32_t r, padh = 0, padw = 0;<br>
+<br>
+        m_param->confWinBottomOffset = m_param->confWinRightOffset = 0;<br>
+<br>
+        m_isAnalysisSave = m_cliopt.saveLevel ? true : false;<br>
+        m_isAnalysisLoad = m_cliopt.loadLevel ? true : false;<br></blockquote><div>[KS] Looks like these two members are redundant? </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        m_param->analysisLoadReuseLevel = m_cliopt.loadLevel;<br>
+        m_param->analysisSaveReuseLevel = m_cliopt.saveLevel;<br>
+        m_param->analysisSave = m_isAnalysisSave ? "save.dat" : NULL;<br>
+        m_param->analysisLoad = m_isAnalysisLoad ? "load.dat" : NULL;<br>
+        m_param->bUseAnalysisFile = 0;<br>
+<br>
+        if (m_isAnalysisLoad)<br>
+        {<br>
+            x265_param *refParam = m_parent->m_passEnc[m_cliopt.refId]->m_param;<br>
+<br>
+            if (m_param->sourceHeight == (refParam->sourceHeight - refParam->confWinBottomOffset) &&<br>
+                m_param->sourceWidth == (refParam->sourceWidth - refParam->confWinRightOffset))<br>
+            {<br>
+                m_parent->m_passEnc[m_id]->m_param->confWinBottomOffset = refParam->confWinBottomOffset;<br>
+                m_parent->m_passEnc[m_id]->m_param->confWinRightOffset = refParam->confWinRightOffset;<br>
+            }<br>
+            else<br>
+            {<br>
+                int srcH = refParam->sourceHeight - refParam->confWinBottomOffset;<br>
+                int srcW = refParam->sourceWidth - refParam->confWinRightOffset;<br>
+<br>
+                double scaleFactorH = double(m_param->sourceHeight / srcH);<br>
+                double scaleFactorW = double(m_param->sourceWidth / srcW);<br>
+<br>
+                int absScaleFactorH = (int)(10 * scaleFactorH + 0.5);<br>
+                int absScaleFactorW = (int)(10 * scaleFactorW + 0.5);<br>
+<br>
+                if (absScaleFactorH == 20 && absScaleFactorW == 20)<br>
+                {<br>
+                    m_param->scaleFactor = 2;<br>
+<br>
+                    m_parent->m_passEnc[m_id]->m_param->confWinBottomOffset = refParam->confWinBottomOffset * 2;<br>
+                    m_parent->m_passEnc[m_id]->m_param->confWinRightOffset = refParam->confWinRightOffset * 2;<br>
+<br>
+                }<br>
+            }<br>
+        }<br>
+<br>
+        int h = m_param->sourceHeight + m_param->confWinBottomOffset;<br>
+        int w = m_param->sourceWidth + m_param->confWinRightOffset;<br>
+        if (h & (m_param->minCUSize - 1))<br>
+        {<br>
+            r = h & (m_param->minCUSize - 1);<br>
+            padh = m_param->minCUSize - r;<br>
+            m_param->confWinBottomOffset += padh;<br>
+<br>
+        }<br>
+<br>
+        if (w & (m_param->minCUSize - 1))<br>
+        {<br>
+            r = w & (m_param->minCUSize - 1);<br>
+            padw = m_param->minCUSize - r;<br>
+            m_param->confWinRightOffset += padw;<br>
+        }<br>
+    }<br>
+<br>
+    void PassEncoder::startThreads()<br>
+    {<br>
+        /* Start slave worker threads */<br>
+        m_threadActive = true;<br>
+        start();<br>
+        /* Start reader threads*/<br>
+        if (m_reader != NULL)<br>
+        {<br>
+            m_reader->m_threadActive = true;<br>
+            m_reader->start();<br>
+        }<br>
+        /* Start scaling worker threads */<br>
+        if (m_scaler != NULL)<br>
+        {<br>
+            m_scaler->m_threadActive = true;<br>
+            m_scaler->start();<br>
+        }<br>
+    }<br>
+<br>
+    void PassEncoder::copyInfo(x265_analysis_data * src)<br>
+    {<br>
+<br>
+        uint32_t written = m_parent->m_analysisWriteCnt[m_id].get();<br>
+<br>
+        int index = written % m_parent->m_queueSize;<br>
+        //If all streams have read analysis data, reuse that position in Queue<br>
+<br>
+        int read = m_parent->m_analysisRead[m_id][index].get();<br>
+        int write = m_parent->m_analysisWrite[m_id][index].get();<br>
+<br>
+        int overwrite = written / m_parent->m_queueSize;<br>
+        bool emptyIdxFound = 0;<br>
+        while (!emptyIdxFound && overwrite)<br>
+        {<br>
+            for (uint32_t i = 0; i < m_parent->m_queueSize; i++)<br>
+            {<br>
+                read = m_parent->m_analysisRead[m_id][i].get();<br>
+                write = m_parent->m_analysisWrite[m_id][i].get();<br>
+                write *= m_cliopt.numRefs;<br>
+<br>
+                if (read == write)<br>
+                {<br>
+                    index = i;<br>
+                    emptyIdxFound = 1;<br>
+                }<br>
+            }<br>
+        }<br>
+<br>
+        x265_analysis_data *m_analysisInfo = &m_parent->m_analysisBuffer[m_id][index];<br>
+<br>
+        memcpy(m_analysisInfo, src, sizeof(x265_analysis_data));<br>
+        x265_alloc_analysis_data(m_param, m_analysisInfo);<br>
+<br>
+        bool isVbv = m_param->rc.vbvBufferSize && m_param->rc.vbvMaxBitrate;<br>
+        if (m_param->bDisableLookahead && isVbv)<br>
+        {<br>
+            memcpy(m_analysisInfo->lookahead.intraSatdForVbv, src->lookahead.intraSatdForVbv, src->numCuInHeight * sizeof(uint32_t));<br>
+            memcpy(m_analysisInfo->lookahead.satdForVbv, src->lookahead.satdForVbv, src->numCuInHeight * sizeof(uint32_t));<br>
+            memcpy(m_analysisInfo->lookahead.intraVbvCost, src->lookahead.intraVbvCost, src->numCUsInFrame * sizeof(uint32_t));<br>
+            memcpy(m_analysisInfo->lookahead.vbvCost, src->lookahead.vbvCost, src->numCUsInFrame * sizeof(uint32_t));<br>
+        }<br>
+<br>
+        if (src->sliceType == X265_TYPE_IDR || src->sliceType == X265_TYPE_I)<br>
+        {<br>
+            if (m_param->analysisSaveReuseLevel < 2)<br>
+                goto ret;<br>
+            x265_analysis_intra_data *intraDst, *intraSrc;<br>
+            intraDst = (x265_analysis_intra_data*)m_analysisInfo->intraData;<br>
+            intraSrc = (x265_analysis_intra_data*)src->intraData;<br>
+            memcpy(intraDst->depth, intraSrc->depth, sizeof(uint8_t) * src->depthBytes);<br>
+            memcpy(intraDst->modes, intraSrc->modes, sizeof(uint8_t) * src->numCUsInFrame * src->numPartitions);<br>
+            memcpy(intraDst->partSizes, intraSrc->partSizes, sizeof(char) * src->depthBytes);<br>
+            memcpy(intraDst->chromaModes, intraSrc->chromaModes, sizeof(uint8_t) * src->depthBytes);<br>
+            if (m_param->rc.cuTree)<br>
+                memcpy(intraDst->cuQPOff, intraSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>
+        }<br>
+        else<br>
+        {<br>
+            bool bIntraInInter = (src->sliceType == X265_TYPE_P || m_param->bIntraInBFrames);<br>
+            int numDir = src->sliceType == X265_TYPE_P ? 1 : 2;<br>
+            memcpy(m_analysisInfo->wt, src->wt, sizeof(WeightParam) * 3 * numDir);<br>
+            if (m_param->analysisSaveReuseLevel < 2)<br>
+                goto ret;<br>
+            x265_analysis_inter_data *interDst, *interSrc;<br>
+            interDst = (x265_analysis_inter_data*)m_analysisInfo->interData;<br>
+            interSrc = (x265_analysis_inter_data*)src->interData;<br>
+            memcpy(interDst->depth, interSrc->depth, sizeof(uint8_t) * src->depthBytes);<br>
+            memcpy(interDst->modes, interSrc->modes, sizeof(uint8_t) * src->depthBytes);<br>
+            if (m_param->rc.cuTree)<br>
+                memcpy(interDst->cuQPOff, interSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>
+            if (m_param->analysisSaveReuseLevel > 4)<br>
+            {<br>
+                memcpy(interDst->partSize, interSrc->partSize, sizeof(uint8_t) * src->depthBytes);<br>
+                memcpy(interDst->mergeFlag, interSrc->mergeFlag, sizeof(uint8_t) * src->depthBytes);<br>
+                if (m_param->analysisSaveReuseLevel == 10)<br>
+                {<br>
+                    memcpy(interDst->interDir, interSrc->interDir, sizeof(uint8_t) * src->depthBytes);<br>
+                    for (int dir = 0; dir < numDir; dir++)<br>
+                    {<br>
+                        memcpy(interDst->mvpIdx[dir], interSrc->mvpIdx[dir], sizeof(uint8_t) * src->depthBytes);<br>
+                        memcpy(interDst->refIdx[dir], interSrc->refIdx[dir], sizeof(int8_t) * src->depthBytes);<br>
+                        memcpy(interDst->mv[dir], interSrc->mv[dir], sizeof(MV) * src->depthBytes);<br>
+                    }<br>
+                    if (bIntraInInter)<br>
+                    {<br>
+                        x265_analysis_intra_data *intraDst = (x265_analysis_intra_data*)m_analysisInfo->intraData;<br>
+                        x265_analysis_intra_data *intraSrc = (x265_analysis_intra_data*)src->intraData;<br>
+                        memcpy(intraDst->modes, intraSrc->modes, sizeof(uint8_t) * src->numPartitions * src->numCUsInFrame);<br>
+                        memcpy(intraDst->chromaModes, intraSrc->chromaModes, sizeof(uint8_t) * src->depthBytes);<br>
+                    }<br>
+               }<br>
+            }<br>
+            if (m_param->analysisSaveReuseLevel != 10)<br>
+                memcpy(interDst->ref, interSrc->ref, sizeof(int32_t) * src->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir);<br></blockquote><div>[KS] Do we support reuse levels other than 1 and 10 ? This condition will never hit if we do not have that support</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        }<br>
+<br>
+ret:<br>
+        //increment analysis Write counter <br>
+        m_parent->m_analysisWriteCnt[m_id].incr();<br>
+        m_parent->m_analysisWrite[m_id][index].incr();<br>
+        return;<br>
+    }<br>
+<br>
+<br>
+    bool PassEncoder::readPicture(x265_picture *dstPic)<br>
+    {<br>
+        /*Check and wait if there any input frames to read*/<br>
+        int ipread = m_parent->m_picReadCnt[m_id].get();<br>
+        int ipwrite = m_parent->m_picWriteCnt[m_id].get();<br>
+<br>
+        bool isAbrLoad = m_isAnalysisLoad && (m_parent->m_numEncodes > 1);<br>
+        while (m_threadActive && (ipread == ipwrite))<br>
+        {<br>
+            ipwrite = m_parent->m_picWriteCnt[m_id].waitForChange(ipwrite);<br>
+        }<br>
+<br>
+        if (m_threadActive && ipread < ipwrite)<br>
+        {<br>
+            /*Get input index to read from inputQueue. If doesn't need analysis info, it need not wait to fetch poc from analysisQueue*/<br>
+            int readPos = ipread % m_parent->m_queueSize;<br>
+            x265_analysis_data* analysisData = 0;<br>
+<br>
+            if (isAbrLoad)<br>
+            {<br>
+                /*If stream is master of each slave pass, then fetch analysis data from prev pass*/<br>
+                int analysisQId = m_cliopt.refId;<br>
+                /*Check and wait if there any analysis Data to read*/<br>
+                int analysisWrite = m_parent->m_analysisWriteCnt[analysisQId].get();<br>
+                int written = analysisWrite * m_parent->m_passEnc[analysisQId]->m_cliopt.numRefs;<br>
+                int analysisRead = m_parent->m_analysisReadCnt[analysisQId].get();<br>
+                <br>
+                while (m_threadActive && written == analysisRead)<br>
+                {<br>
+                    analysisWrite = m_parent->m_analysisWriteCnt[analysisQId].waitForChange(analysisWrite);<br>
+                    written = analysisWrite * m_parent->m_passEnc[analysisQId]->m_cliopt.numRefs;<br>
+                }<br>
+<br>
+                if (analysisRead < written)<br>
+                {<br>
+                    int analysisIdx = 0;<br>
+                    if (!m_param->bDisableLookahead)<br>
+                    {<br>
+                        bool analysisdRead = false;<br>
+                        while ((analysisRead < written) && !analysisdRead)<br>
+                        {<br>
+                            while (analysisWrite < ipread)<br>
+                            {<br>
+                                analysisWrite = m_parent->m_analysisWriteCnt[analysisQId].waitForChange(analysisWrite);<br>
+                                written = analysisWrite * m_parent->m_passEnc[analysisQId]->m_cliopt.numRefs;<br>
+                            }<br>
+                            for (uint32_t i = 0; i < m_parent->m_queueSize; i++)<br>
+                            {<br>
+                                analysisData = &m_parent->m_analysisBuffer[analysisQId][i];<br>
+                                int read = m_parent->m_analysisRead[analysisQId][i].get();<br>
+                                int write = m_parent->m_analysisWrite[analysisQId][i].get() * m_parent->m_passEnc[analysisQId]->m_cliopt.numRefs;<br>
+                                if ((analysisData->poc == (uint32_t)(ipread)) && (read < write))<br>
+                                {<br>
+                                    analysisIdx = i;<br>
+                                    analysisdRead = true;<br>
+                                    break;<br>
+                                }<br>
+                            }<br>
+                        }<br>
+                    }<br>
+                    else<br>
+                    {<br>
+                        analysisIdx = analysisRead % m_parent->m_queueSize;<br>
+                        analysisData = &m_parent->m_analysisBuffer[analysisQId][analysisIdx];<br>
+                        readPos = analysisData->poc % m_parent->m_queueSize;<br>
+                        while ((ipwrite < readPos) || ((ipwrite - 1) < (int)analysisData->poc))<br>
+                        {<br>
+                            ipwrite = m_parent->m_picWriteCnt[m_id].waitForChange(ipwrite);<br>
+                        }<br>
+                    }<br>
+<br>
+                    m_lastIdx = analysisIdx;<br>
+                }<br>
+                else<br>
+                    return false;<br>
+            }<br>
+<br>
+<br>
+            x265_picture *srcPic = (x265_picture*)(m_parent->m_inputPicBuffer[m_id][readPos]);<br>
+<br>
+            x265_picture *pic = (x265_picture*)(dstPic);<br>
+            pic->colorSpace = srcPic->colorSpace;<br>
+            pic->bitDepth = srcPic->bitDepth;<br>
+            pic->framesize = srcPic->framesize;<br>
+            pic->height = srcPic->height;<br>
+            pic->pts = srcPic->pts;<br>
+            pic->dts = srcPic->dts;<br>
+            pic->reorderedPts = srcPic->reorderedPts;<br>
+            pic->poc = srcPic->poc;<br>
+            pic->analysisData = srcPic->analysisData;<br>
+            pic->userSEI = srcPic->userSEI;<br>
+            pic->stride[0] = srcPic->stride[0];<br>
+            pic->stride[1] = srcPic->stride[1];<br>
+            pic->stride[2] = srcPic->stride[2];<br>
+            pic->planes[0] = srcPic->planes[0];<br>
+            pic->planes[1] = srcPic->planes[1];<br>
+            pic->planes[2] = srcPic->planes[2];<br>
+            if (isAbrLoad)<br>
+                pic->analysisData = *analysisData;<br>
+            return true;<br>
+        }<br>
+        else<br>
+            return false;<br>
+    }<br>
+<br>
+    void PassEncoder::threadMain()<br>
+    {<br>
+<br>
+#if ENABLE_LIBVMAF<br>
+        x265_vmaf_data* vmafdata = cliopt.vmafData;<br>
+#endif<br></blockquote><div>[KS] m_cliopt. Have you tested enabling libvmaf? </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        /* This allows muxers to modify bitstream format */<br>
+        m_cliopt.output->setParam(m_param);<br>
+<br>
+        ReconPlay* reconPlay = NULL;<br>
+        if (m_cliopt.reconPlayCmd)<br>
+            reconPlay = new ReconPlay(m_cliopt.reconPlayCmd, *m_param);<br>
+<br></blockquote><div>[KS] Is there a reason you have moved the encoder_open and zoneparse API calls out of threadMain() ?<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        if (signal(SIGINT, sigint_handler) == SIG_ERR)<br>
+            x265_log(m_param, X265_LOG_ERROR, "Unable to register CTRL+C handler: %s\n", strerror(errno));<br>
+<br>
+        x265_picture pic_orig, pic_out;<br>
+        x265_picture *pic_in = &pic_orig;<br>
+        /* Allocate recon picture if analysis save/load is enabled */<br>
+        std::priority_queue<int64_t>* pts_queue = m_cliopt.output->needPTS() ? new std::priority_queue<int64_t>() : NULL;<br>
+        x265_picture *pic_recon = (m_cliopt.recon || m_param->analysisSave || m_param->analysisLoad || pts_queue || reconPlay || m_param->csvLogLevel) ? &pic_out : NULL;<br>
+        uint32_t inFrameCount = 0;<br>
+        uint32_t outFrameCount = 0;<br>
+        x265_nal *p_nal;<br>
+        x265_stats stats;<br>
+        uint32_t nal;<br>
+        int16_t *errorBuf = NULL;<br>
+        bool bDolbyVisionRPU = false;<br>
+        uint8_t *rpuPayload = NULL;<br>
+        int inputPicNum = 1;<br>
+        x265_picture picField1, picField2;<br>
+        x265_analysis_data* analysisInfo = (x265_analysis_data*)(&pic_out.analysisData);<br>
+        bool isAbrSave = m_isAnalysisSave && (m_parent->m_numEncodes > 1);<br>
+<br>
+        if (!m_param->bRepeatHeaders && !m_param->bEnableSvtHevc)<br>
+        {<br>
+            if (x265_encoder_headers(m_encoder, &p_nal, &nal) < 0)<br>
+            {<br>
+                x265_log(m_param, X265_LOG_ERROR, "Failure generating stream headers %d\n", m_id);<br>
+                goto fail;<br>
+            }<br>
+            else<br>
+                m_cliopt.totalbytes += m_cliopt.output->writeHeaders(p_nal, nal);<br>
+        }<br>
+<br>
+        if (m_param->bField && m_param->interlaceMode)<br>
+        {<br>
+            x265_picture_init(m_param, &picField1);<br>
+            x265_picture_init(m_param, &picField2);<br>
+            // return back the original height of input<br>
+            m_param->sourceHeight *= 2;<br>
+            x265_picture_init(m_param, &pic_orig);<br>
+        }<br>
+        else<br>
+            x265_picture_init(m_param, &pic_orig);<br>
+<br>
+        if (m_param->dolbyProfile && m_cliopt.dolbyVisionRpu)<br>
+        {<br>
+            rpuPayload = X265_MALLOC(uint8_t, 1024);<br>
+            pic_in->rpu.payload = rpuPayload;<br>
+            if (pic_in->rpu.payload)<br>
+                bDolbyVisionRPU = true;<br>
+        }<br>
+<br>
+        if (m_cliopt.bDither)<br>
+        {<br>
+            errorBuf = X265_MALLOC(int16_t, m_param->sourceWidth + 1);<br>
+            if (errorBuf)<br>
+                memset(errorBuf, 0, (m_param->sourceWidth + 1) * sizeof(int16_t));<br>
+            else<br>
+                m_cliopt.bDither = false;<br>
+        }<br>
+<br>
+        // main encoder loop<br>
+        while (pic_in && !b_ctrl_c)<br>
+        {<br>
+            pic_orig.poc = (m_param->bField && m_param->interlaceMode) ? inFrameCount * 2 : inFrameCount;<br>
+            if (m_cliopt.qpfile)<br>
+            {<br>
+                if (!m_cliopt.parseQPFile(pic_orig))<br>
+                {<br>
+                    x265_log(NULL, X265_LOG_ERROR, "can't parse qpfile for frame %d\n", pic_in->poc);<br>
+                    fclose(m_cliopt.qpfile);<br>
+                    m_cliopt.qpfile = NULL;<br>
+                }<br>
+            }<br>
+<br>
+            if (m_cliopt.framesToBeEncoded && inFrameCount >= m_cliopt.framesToBeEncoded)<br>
+            {<br>
+                pic_in = NULL;<br>
+            }<br></blockquote><div>[KS] remove brace </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+            else if (readPicture(pic_in))<br>
+                inFrameCount++;<br>
+            else<br>
+                pic_in = NULL;<br>
+<br>
+            if (pic_in)<br>
+            {<br>
+                if (pic_in->bitDepth > m_param->internalBitDepth && m_cliopt.bDither)<br>
+                {<br>
+                    x265_dither_image(pic_in, m_cliopt.input->getWidth(), m_cliopt.input->getHeight(), errorBuf, m_param->internalBitDepth);<br>
+                    pic_in->bitDepth = m_param->internalBitDepth;<br>
+                }<br>
+                /* Overwrite PTS */<br>
+                pic_in->pts = pic_in->poc;<br>
+<br>
+                // convert to field<br>
+                if (m_param->bField && m_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>
+                        size_t fieldFrameSize = (size_t)pic_in->framesize >> 1;<br>
+                        char* field1Buf = X265_MALLOC(char, fieldFrameSize);<br>
+                        char* field2Buf = X265_MALLOC(char, fieldFrameSize);<br>
+<br>
+                        int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0];<br>
+                        uint64_t 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></blockquote><div>[KS] There was a ToDo to handle userdata of pic-in here. Shall we preserve that for the future?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+                    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 (m_param->bField && m_param->interlaceMode)<br>
+                    {<br>
+                        if (rpuParser(&picField1, m_cliopt.dolbyVisionRpu) > 0)<br>
+                            goto fail;<br>
+                        if (rpuParser(&picField2, m_cliopt.dolbyVisionRpu) > 0)<br>
+                            goto fail;<br>
+                    }<br>
+                    else<br>
+                    {<br>
+                        if (rpuParser(pic_in, m_cliopt.dolbyVisionRpu) > 0)<br>
+                            goto fail;<br>
+                    }<br>
+                }<br>
+            }<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 = x265_encoder_encode(m_encoder, &p_nal, &nal, picInput, pic_recon);<br>
+<br>
+                int idx = (inFrameCount - 1) % m_parent->m_queueSize;<br>
+                m_parent->m_picIdxReadCnt[m_id][idx].incr();<br>
+                m_parent->m_picReadCnt[m_id].incr();<br>
+                if (m_cliopt.loadLevel && picInput)<br>
+                {<br>
+                    m_parent->m_analysisReadCnt[m_cliopt.refId].incr();<br>
+                    m_parent->m_analysisRead[m_cliopt.refId][m_lastIdx].incr();<br>
+                }<br>
+<br>
+                if (numEncoded < 0)<br>
+                {<br>
+                    b_ctrl_c = 1;<br>
+                    break;<br>
+                }<br>
+<br>
+                if (reconPlay && numEncoded)<br>
+                    reconPlay->writePicture(*pic_recon);<br>
+<br>
+                outFrameCount += numEncoded;<br>
+<br>
+                if (isAbrSave && numEncoded)<br>
+                {<br>
+                    copyInfo(analysisInfo);<br>
+                }<br>
+<br>
+                if (numEncoded && pic_recon && m_cliopt.recon)<br>
+                    m_cliopt.recon->writePicture(pic_out);<br>
+                if (nal)<br>
+                {<br>
+                    m_cliopt.totalbytes += m_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>
+                m_cliopt.printStatus(outFrameCount);<br>
+            }<br>
+        }<br>
+<br>
+        /* Flush the encoder */<br>
+        while (!b_ctrl_c)<br>
+        {<br>
+            int numEncoded = x265_encoder_encode(m_encoder, &p_nal, &nal, NULL, pic_recon);<br>
+            if (numEncoded < 0)<br>
+                break;<br>
+ <br>
+            if (reconPlay && numEncoded)<br>
+                reconPlay->writePicture(*pic_recon);<br>
+<br>
+            outFrameCount += numEncoded;<br>
+            if (isAbrSave && numEncoded)<br>
+            {<br>
+                copyInfo(analysisInfo);<br>
+            }<br>
+<br>
+            if (numEncoded && pic_recon && m_cliopt.recon)<br>
+                m_cliopt.recon->writePicture(pic_out);<br>
+            if (nal)<br>
+            {<br>
+                m_cliopt.totalbytes += m_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>
+            m_cliopt.printStatus(outFrameCount);<br>
+<br>
+            if (!numEncoded)<br>
+                break;<br>
+        }<br>
+<br>
+        if (bDolbyVisionRPU)<br>
+        {<br>
+            if (fgetc(m_cliopt.dolbyVisionRpu) != EOF)<br>
+                x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU count is greater than frame count\n");<br>
+            x265_log(NULL, X265_LOG_INFO, "VES muxing with Dolby Vision RPU file successful\n");<br>
+        }<br>
+<br>
+        if (bDolbyVisionRPU)<br>
+        {<br>
+            if (fgetc(m_cliopt.dolbyVisionRpu) != EOF)<br>
+                x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU count is greater than frame count\n");<br>
+            x265_log(NULL, X265_LOG_INFO, "VES muxing with Dolby Vision RPU file successful\n");<br>
+        }<br>
+<br>
+        /* clear progress report */<br>
+        if (m_cliopt.bProgress)<br>
+            fprintf(stderr, "%*s\r", 80, " ");<br>
+<br>
+    fail:<br>
+<br>
+        delete reconPlay;<br>
+<br>
+        x265_encoder_get_stats(m_encoder, &stats, sizeof(stats));<br>
+        if (m_param->csvfn && !b_ctrl_c)<br>
+#if ENABLE_LIBVMAF<br>
+            x265_vmaf_encoder_log(encoder, argc, argv, param, vmafdata);<br>
+#else<br>
+            x265_encoder_log(m_encoder, 0, NULL);<br>
+#endif<br>
+<br>
+        int64_t second_largest_pts = 0;<br>
+        int64_t largest_pts = 0;<br>
+<br>
+        m_cliopt.output->closeFile(largest_pts, second_largest_pts);<br>
+<br>
+        if (b_ctrl_c)<br>
+            general_log(m_param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",<br>
+                m_cliopt.seek + inFrameCount, stats.encodedPictureCount);<br>
+<br>
+        X265_FREE(errorBuf);<br>
+        X265_FREE(rpuPayload);<br>
+<br>
+        m_threadActive = false;<br>
+        m_parent->m_numActiveEncodes.decr();<br>
+    }<br>
+<br>
+    void PassEncoder::close()<br>
+    {<br>
+        x265_param_free(m_param);<br>
+        x265_encoder_close(m_encoder);<br>
+    }<br>
+<br>
+    void PassEncoder::destroy()<br>
+    {<br>
+        if (m_reader)<br>
+        {<br>
+            delete m_reader;<br>
+        }<br>
+        else<br>
+        {<br>
+            m_scaler->destroy();<br>
+            delete m_scaler;<br>
+        }<br>
+    }<br>
+<br>
+    Scaler::Scaler(int threadId, int threadNum, int id, VideoDesc *src, VideoDesc *dst, PassEncoder *parentEnc)<br>
+    {<br>
+        m_parentEnc = parentEnc;<br>
+        m_id = id;<br>
+        m_srcFormat = src;<br>
+        m_dstFormat = dst;<br>
+        m_threadActive = false;<br>
+        m_scaleFrameSize = 0;<br>
+        m_filterManager = NULL;<br>
+        m_threadId = threadId;<br>
+        m_threadTotal = threadNum;<br>
+<br>
+        int csp = dst->m_csp;<br>
+        uint32_t pixelbytes = dst->m_inputDepth > 8 ? 2 : 1;<br>
+        for (int i = 0; i < x265_cli_csps[csp].planes; i++)<br>
+        {<br>
+            int w = dst->m_width >> x265_cli_csps[csp].width[i];<br>
+            int h = dst->m_height >> x265_cli_csps[csp].height[i];<br>
+            m_scalePlanes[i] = w * h * pixelbytes;<br>
+            m_scaleFrameSize += m_scalePlanes[i];<br>
+        }<br>
+<br>
+        if (src->m_height != dst->m_height || src->m_width != dst->m_width)<br>
+        {<br>
+            m_filterManager = new ScalerFilterManager;<br>
+            m_filterManager->init(4, m_srcFormat, m_dstFormat);<br>
+        }<br>
+    }<br>
+<br>
+    bool Scaler::scalePic(x265_picture * destination, x265_picture * source)<br>
+    {<br>
+        if (!destination || !source)<br>
+            return false;<br>
+        x265_param* param = m_parentEnc->m_param;<br>
+        int pixelBytes = m_dstFormat->m_inputDepth > 8 ? 2 : 1; </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        if (m_srcFormat->m_height != m_dstFormat->m_height || m_srcFormat->m_width != m_dstFormat->m_width)<br>
+        {<br>
+            void **srcPlane = NULL, **dstPlane = NULL;<br>
+            int srcStride[3], dstStride[3];<br>
+            destination->bitDepth = source->bitDepth;<br>
+            destination->colorSpace = source->colorSpace;<br>
+            destination->pts = source->pts;<br>
+            destination->dts = source->dts;<br>
+            destination->reorderedPts = source->reorderedPts;<br>
+            destination->poc = source->poc;<br>
+            destination->userSEI = source->userSEI;<br>
+            srcPlane = source->planes;<br>
+            dstPlane = destination->planes;<br>
+            srcStride[0] = source->stride[0];<br>
+            destination->stride[0] = m_dstFormat->m_width * pixelBytes;<br>
+            dstStride[0] = destination->stride[0];<br>
+            if (param->internalCsp != X265_CSP_I400)<br>
+            {<br>
+                srcStride[1] = source->stride[1];<br>
+                srcStride[2] = source->stride[2];<br>
+                destination->stride[1] = destination->stride[0] >> x265_cli_csps[param->internalCsp].width[1];<br>
+                destination->stride[2] = destination->stride[0] >> x265_cli_csps[param->internalCsp].width[2];<br>
+                dstStride[1] = destination->stride[1];<br>
+                dstStride[2] = destination->stride[2];<br>
+            }<br>
+            if (m_scaleFrameSize)<br>
+            {<br>
+                m_filterManager->scale_pic(srcPlane, dstPlane, srcStride, dstStride);<br>
+                return true;<br>
+            }<br>
+            else<br>
+                x265_log(param, X265_LOG_INFO, "Empty frame received\n");<br>
+        }<br>
+        return false;<br>
+    }<br>
+<br>
+    void Scaler::threadMain()<br>
+    {<br>
+        THREAD_NAME("Scaler", m_id);<br>
+<br>
+        /* unscaled picture is stored in the last index */<br>
+        uint32_t srcId = m_id - 1;<br>
+        int QDepth = m_parentEnc->m_parent->m_queueSize;<br>
+        while (!m_parentEnc->m_doneReading)<br>
+        {<br>
+<br>
+            uint32_t scaledWritten = m_parentEnc->m_parent->m_picWriteCnt[m_id].get();<br>
+<br>
+            if (m_parentEnc->m_cliopt.framesToBeEncoded && scaledWritten >= m_parentEnc->m_cliopt.framesToBeEncoded)<br>
+                break;<br>
+<br>
+            if (m_threadTotal > 1 && (m_threadId != scaledWritten % m_threadTotal))<br>
+            {<br>
+                continue;<br>
+            }<br>
+            uint32_t written = m_parentEnc->m_parent->m_picWriteCnt[srcId].get();<br>
+<br>
+            /*If all the input pictures are scaled by the current scale worker thread wait for input pictures*/<br>
+            while (m_threadActive && (scaledWritten == written)) {<br>
+                written = m_parentEnc->m_parent->m_picWriteCnt[srcId].waitForChange(written);<br>
+            }<br>
+<br>
+            if (m_threadActive && scaledWritten < written)<br>
+            {<br>
+<br>
+                int scaledWriteIdx = scaledWritten % QDepth;<br>
+                int overWritePicBuffer = scaledWritten / QDepth;<br>
+                int read = m_parentEnc->m_parent->m_picIdxReadCnt[m_id][scaledWriteIdx].get();<br>
+<br>
+                while (overWritePicBuffer && read < overWritePicBuffer)<br>
+                {<br>
+                    read = m_parentEnc->m_parent->m_picIdxReadCnt[m_id][scaledWriteIdx].waitForChange(read);<br>
+                }<br>
+<br>
+                if (!m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWriteIdx])<br>
+                {<br>
+                    int framesize = 0;<br>
+                    int planesize[3];<br>
+                    int csp = m_dstFormat->m_csp;<br>
+                    int stride[3];<br>
+                    stride[0] = m_dstFormat->m_width;<br>
+                    stride[1] = stride[0] >> x265_cli_csps[csp].width[1];<br>
+                    stride[2] = stride[0] >> x265_cli_csps[csp].width[2];<br>
+                    for (int i = 0; i < x265_cli_csps[csp].planes; i++)<br>
+                    {<br>
+                        uint32_t h = m_dstFormat->m_height >> x265_cli_csps[csp].height[i];<br>
+                        planesize[i] = h * stride[i];<br>
+                        framesize += planesize[i];<br>
+                    }<br>
+<br>
+                    m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWriteIdx] = x265_picture_alloc();<br>
+                    x265_picture_init(m_parentEnc->m_param, m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWriteIdx]);<br>
+<br>
+                    ((x265_picture*)m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWritten % QDepth])->framesize = framesize;<br>
+                    for (int32_t j = 0; j < x265_cli_csps[csp].planes; j++)<br>
+                    {<br>
+                        m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWritten % QDepth]->planes[j] = X265_MALLOC(char, planesize[j]);<br>
+                    }<br>
+                }<br>
+<br>
+                x265_picture *srcPic = m_parentEnc->m_parent->m_inputPicBuffer[srcId][scaledWritten % QDepth];<br>
+                x265_picture* destPic = m_parentEnc->m_parent->m_inputPicBuffer[m_id][scaledWriteIdx];<br>
+<br>
+                // Enqueue this picture up with the current encoder so that it will asynchronously encode<br>
+                if (!scalePic(destPic, srcPic))<br>
+                    x265_log(NULL, X265_LOG_ERROR, "Unable to copy scaled input picture to input queue \n");<br>
+                else<br>
+                    m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();<br>
+                m_scaledWriteCnt.incr();<br>
+                m_parentEnc->m_parent->m_picIdxReadCnt[srcId][scaledWriteIdx].incr();<br>
+            }<br>
+            if (m_threadTotal > 1)<br>
+            {<br>
+                written = m_parentEnc->m_parent->m_picWriteCnt[srcId].get();<br>
+                int totalWrite = written / m_threadTotal;<br>
+                if (written % m_threadTotal > m_threadId)<br>
+                    totalWrite++;<br>
+                if (totalWrite == m_scaledWriteCnt.get())<br>
+                {<br>
+                    m_parentEnc->m_parent->m_picWriteCnt[srcId].poke();<br>
+                    m_parentEnc->m_parent->m_picWriteCnt[m_id].poke();<br>
+                    break;<br>
+                }<br>
+            }<br>
+            else<br>
+            {<br>
+                /* Once end of video is reached and all frames are scaled, release wait on picwritecount */<br>
+                scaledWritten = m_parentEnc->m_parent->m_picWriteCnt[m_id].get();<br>
+                written = m_parentEnc->m_parent->m_picWriteCnt[srcId].get();<br>
+                if (written == scaledWritten)<br>
+                {<br>
+                    m_parentEnc->m_parent->m_picWriteCnt[srcId].poke();<br>
+                    m_parentEnc->m_parent->m_picWriteCnt[m_id].poke();<br>
+                    break;<br>
+                }<br>
+            }<br>
+<br>
+        }<br>
+        m_threadActive = false;<br>
+        destroy();<br>
+    }<br>
+<br>
+    Reader::Reader(int id, PassEncoder *parentEnc)<br>
+    {<br>
+        m_parentEnc = parentEnc;<br>
+        m_id = id;<br>
+        m_input = parentEnc->m_input;<br>
+    }<br>
+<br>
+    void Reader::threadMain()<br>
+    {<br>
+        THREAD_NAME("Reader", m_id);<br>
+<br>
+        int QDepth = m_parentEnc->m_parent->m_queueSize;<br>
+        x265_picture* src = x265_picture_alloc();<br>
+        x265_picture_init(m_parentEnc->m_param, src);<br>
+<br>
+        while (!m_parentEnc->m_doneReading)<br>
+        {<br>
+            uint32_t written = m_parentEnc->m_parent->m_picWriteCnt[m_id].get();<br>
+            uint32_t writeIdx = written % QDepth;<br>
+            uint32_t read = m_parentEnc->m_parent->m_picIdxReadCnt[m_id][writeIdx].get();<br>
+            uint32_t overWritePicBuffer = written / QDepth;<br>
+<br>
+            if (m_parentEnc->m_cliopt.framesToBeEncoded && written >= m_parentEnc->m_cliopt.framesToBeEncoded)<br>
+                break;<br>
+<br>
+            while (overWritePicBuffer && read < overWritePicBuffer)<br>
+            {<br>
+                read = m_parentEnc->m_parent->m_picIdxReadCnt[m_id][writeIdx].waitForChange(read);<br>
+            }<br>
+<br>
+            if (!m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx])<br>
+            {<br>
+                m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx] = x265_picture_alloc();<br>
+                x265_picture_init(m_parentEnc->m_param, m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx]);<br>
+            }<br>
+<br>
+            x265_picture* dest = m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx];<br>
+            if (m_input->readPicture(*src))<br>
+            {<br>
+                dest->poc = src->poc;<br>
+                dest->pts = src->pts;<br>
+                dest->userSEI = src->userSEI;<br>
+                dest->bitDepth = src->bitDepth;<br>
+                dest->framesize = src->framesize;<br>
+                dest->height = src->height;<br>
+                dest->width = src->width;<br>
+                dest->colorSpace = src->colorSpace;<br>
+                dest->userSEI = src->userSEI;<br>
+                dest->rpu.payload = src->rpu.payload;<br>
+                dest->picStruct = src->picStruct;<br>
+                dest->stride[0] = src->stride[0];<br>
+                dest->stride[1] = src->stride[1];<br>
+                dest->stride[2] = src->stride[2];<br>
+<br>
+                if (!dest->planes[0])<br>
+                    dest->planes[0] = X265_MALLOC(char, dest->framesize);<br>
+<br>
+                memcpy(dest->planes[0], src->planes[0], src->framesize * sizeof(char));<br>
+                dest->planes[1] = (char*)dest->planes[0] + src->stride[0] * src->height;<br>
+                dest->planes[2] = (char*)dest->planes[1] + src->stride[1] * (src->height >> x265_cli_csps[src->colorSpace].height[1]);<br>
+                m_parentEnc->m_parent->m_picWriteCnt[m_id].incr();<br>
+            }<br>
+            else<br>
+            {<br>
+                m_parentEnc->m_parent->m_picWriteCnt[m_id].poke();<br>
+                break;<br>
+            }<br>
+        }<br>
+        x265_picture_free(src);<br>
+        m_threadActive = false;<br>
+    }<br>
+}<br>
diff -r 7ebf4b9369b3 -r 3eccfeafc040 source/abrEncApp.h<br>
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000<br>
+++ b/source/abrEncApp.h        Wed Feb 26 16:37:13 2020 +0530<br>
@@ -0,0 +1,160 @@<br>
+/*****************************************************************************<br>
+* Copyright (C) 2013-2020 MulticoreWare, Inc<br>
+*<br>
+* Authors: Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com" target="_blank">pooja@multicorewareinc.com</a>><br>
+*          Aruna Matheswaran <<a href="mailto:aruna@multicorewareinc.com" target="_blank">aruna@multicorewareinc.com</a>><br>
+*           <br>
+*<br>
+* This program is free software; you can redistribute it and/or modify<br>
+* it under the terms of the GNU General Public License as published by<br>
+* the Free Software Foundation; either version 2 of the License, or<br>
+* (at your option) any later version.<br>
+*<br>
+* This program is distributed in the hope that it will be useful,<br>
+* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
+* GNU General Public License for more details.<br>
+*<br>
+* You should have received a copy of the GNU General Public License<br>
+* along with this program; if not, write to the Free Software<br>
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.<br>
+*<br>
+* This program is also available under a commercial proprietary license.<br>
+* For more information, contact us at license @ <a href="http://x265.com" rel="noreferrer" target="_blank">x265.com</a>.<br>
+*****************************************************************************/<br>
+<br>
+#ifndef ABR_ENCODE_H<br>
+#define ABR_ENCODE_H<br>
+<br>
+#include "x265.h"<br>
+#include "scaler.h"<br>
+#include "threading.h"<br>
+#include "x265cli.h"<br>
+<br>
+namespace X265_NS {<br>
+    // private namespace<br>
+<br>
+    class PassEncoder;<br>
+    class Scaler;<br>
+    class Reader;<br>
+<br>
+    class AbrEncoder<br>
+    {<br>
+    public:<br>
+        uint8_t           m_numEncodes;<br>
+        PassEncoder        **m_passEnc;<br>
+        uint32_t           m_queueSize;<br>
+        ThreadSafeInteger  m_numActiveEncodes;<br>
+<br>
+        x265_picture       ***m_inputPicBuffer; //[numEncodes][queueSize]<br>
+        x265_analysis_data **m_analysisBuffer; //[numEncodes][queueSize]<br>
+        int                **m_readFlag;<br>
+<br>
+        ThreadSafeInteger  *m_picWriteCnt;<br>
+        ThreadSafeInteger  *m_picReadCnt;<br>
+        ThreadSafeInteger  **m_picIdxReadCnt;<br>
+        ThreadSafeInteger  *m_analysisWriteCnt; //[numEncodes][queueSize]<br>
+        ThreadSafeInteger  *m_analysisReadCnt; //[numEncodes][queueSize]<br>
+        ThreadSafeInteger  **m_analysisWrite; //[numEncodes][queueSize]<br>
+        ThreadSafeInteger  **m_analysisRead; //[numEncodes][queueSize]<br>
+<br>
+        AbrEncoder(CLIOptions cliopt[], uint8_t numEncodes, int& ret);<br>
+        bool allocBuffers();<br>
+        void closeEncoder();<br>
+        void destroy();<br>
+<br>
+    };<br>
+<br>
+    class PassEncoder : public Thread<br>
+    {<br>
+    public:<br>
+<br>
+        uint32_t m_id;<br>
+        x265_param *m_param;<br>
+        AbrEncoder *m_parent;<br>
+        x265_encoder *m_encoder;<br>
+        Reader *m_reader;<br>
+        Scaler *m_scaler;<br>
+<br>
+        bool m_reqScale;<br>
+        bool m_isScaled;<br></blockquote><div>[KS] unused class members </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        bool m_isAnalysisSave;<br>
+        bool m_isAnalysisLoad;<br>
+        bool m_doneReading;<br>
+<br>
+        int m_threadActive;<br>
+        int m_lastIdx;<br>
+        uint32_t m_outputNalsCount;<br>
+<br>
+        x265_picture **m_inputPicBuffer;<br>
+        x265_analysis_data **m_analysisBuffer;<br>
+        x265_nal **m_outputNals;<br>
+        x265_picture **m_outputRecon;<br>
+<br>
+        CLIOptions m_cliopt;<br>
+        InputFile* m_input;<br>
+        const char* m_reconPlayCmd;<br>
+        FILE*    m_qpfile;<br>
+        FILE*    m_zoneFile;<br>
+        FILE*    m_dolbyVisionRpu;/* File containing Dolby Vision BL RPU metadata */<br>
+<br>
+<br>
+<br>
+        PassEncoder(uint32_t id, CLIOptions cliopt, AbrEncoder *parent);<br>
+        int init(int &result);<br>
+        void setReuseLevel();<br>
+<br>
+        void startThreads();<br>
+        void copyInfo(x265_analysis_data *src);<br>
+<br>
+        bool readPicture(x265_picture*);<br>
+        void close();<br>
+        void destroy();<br>
+<br>
+    private:<br>
+        void threadMain();<br>
+    };<br>
+<br>
+    class Scaler : public Thread<br>
+    {<br>
+    public:<br>
+        PassEncoder *m_parentEnc;<br>
+        int m_id;<br>
+        int m_scalePlanes[3];<br>
+        int m_scaleFrameSize;<br>
+        uint32_t m_threadId;<br>
+        uint32_t m_threadTotal;<br>
+        ThreadSafeInteger m_scaledWriteCnt;<br>
+        VideoDesc* m_srcFormat;<br>
+        VideoDesc* m_dstFormat;<br>
+        int m_threadActive;<br>
+        ScalerFilterManager* m_filterManager;<br>
+<br>
+        Scaler(int threadId, int threadNum, int id, VideoDesc *src, VideoDesc * dst, PassEncoder *parentEnc);<br>
+        bool scalePic(x265_picture *destination, x265_picture *source);<br>
+        void threadMain();<br>
+        void destroy()<br>
+        {<br>
+            if (m_filterManager)<br>
+            {<br>
+                delete m_filterManager;<br>
+                m_filterManager = NULL;<br>
+            }<br>
+        }<br>
+    };<br>
+<br>
+    class Reader : public Thread<br>
+    {<br>
+    public:<br>
+        PassEncoder *m_parentEnc;<br>
+        int m_id;<br>
+        InputFile* m_input;<br>
+        int m_threadActive;<br>
+<br>
+        Reader(int id, PassEncoder *parentEnc);<br>
+        void threadMain();<br>
+    };<br>
+}<br>
+<br>
+#endif // ifndef ABR_ENCODE_H<br>
+#pragma once<br>
diff -r 7ebf4b9369b3 -r 3eccfeafc040 source/common/threading.h<br>
--- a/source/common/threading.h Wed Feb 26 14:40:35 2020 +0530<br>
+++ b/source/common/threading.h Wed Feb 26 16:37:13 2020 +0530<br>
@@ -238,6 +238,14 @@<br>
         LeaveCriticalSection(&m_cs);<br>
     }<br>
<br>
+    void decr()<br>
+    {<br>
+        EnterCriticalSection(&m_cs);<br>
+        m_val--;<br>
+        WakeAllConditionVariable(&m_cv);<br>
+        LeaveCriticalSection(&m_cs);<br>
+    }<br>
+<br>
 protected:<br>
<br>
     CRITICAL_SECTION   m_cs;<br>
@@ -436,6 +444,14 @@<br>
         pthread_mutex_unlock(&m_mutex);<br>
     }<br>
<br>
+    void decr()<br>
+    {<br>
+        pthread_mutex_lock(&m_mutex);<br>
+        m_val--;<br>
+        pthread_cond_broadcast(&m_cond);<br>
+        pthread_mutex_unlock(&m_mutex);<br>
+    }<br>
+<br>
 protected:<br>
<br>
     pthread_mutex_t m_mutex;<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><br clear="all"><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div><div dir="ltr"><span style="color:rgb(0,0,0)">Regards,<br>Kavitha</span></div></div></div></div></div>