changeset 12651:303ff9e4546d

Cleanup
author Aruna Matheswaran <aruna@multicorewareinc.com>
date Wed, 15 Apr 2020 18:44:54 +0530
parents 193db4916b9f
children df0886d58b86
files source/abrEncApp.cpp source/abrEncApp.h source/x265.cpp source/x265cli.cpp source/x265cli.h
diffstat 5 files changed, 439 insertions(+-), 433 deletions(-) [+]
line wrap: on
line diff
--- a/source/abrEncApp.cpp	Mon May 04 11:50:39 2020 +0530
+++ b/source/abrEncApp.cpp	Wed Apr 15 18:44:54 2020 +0530
@@ -41,62 +41,6 @@ static void sigint_handler(int)
     b_ctrl_c = 1;
 }
 
-#define START_CODE 0x00000001
-#define START_CODE_BYTES 4
-
-/* 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;
-
-    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))
-    {
-        code = (code << 8) | byteVal;
-        if (bytesRead++ < 3)
-            continue;
-        if (bytesRead >= 1024)
-        {
-            x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU size in POC %d\n", pic->pts);
-            return 1;
-        }
-
-        if (code != START_CODE)
-            pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;
-        else
-            return 0;
-    }
-
-    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++)
-    {
-        pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;
-        code = (code << 8);
-    }
-    if (!pic->rpu.payloadSize)
-        x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU not found for POC %d\n", pic->pts);
-    return 0;
-}
-
-
 namespace X265_NS {
     // private namespace
 #define X265_INPUT_QUEUE_SIZE 250
@@ -150,8 +94,10 @@ namespace X265_NS {
             m_inputPicBuffer[pass] = X265_MALLOC(x265_picture*, m_queueSize);
             for (uint32_t idx = 0; idx < m_queueSize; idx++)
             {
-                m_inputPicBuffer[pass][idx] = NULL;
+                m_inputPicBuffer[pass][idx] = x265_picture_alloc();
+                x265_picture_init(m_passEnc[pass]->m_param, m_inputPicBuffer[pass][idx]);
             }
+
             m_analysisBuffer[pass] = X265_MALLOC(x265_analysis_data, m_queueSize);
             m_picIdxReadCnt[pass] = new ThreadSafeInteger[m_queueSize];
             m_analysisWrite[pass] = new ThreadSafeInteger[m_queueSize];
@@ -161,32 +107,25 @@ namespace X265_NS {
         return true;
     }
 
-    void AbrEncoder::closeEncoder()
-    {
-        for (uint8_t pidx = 0; pidx < m_numEncodes; pidx++)
-        {
-            PassEncoder *passWorker = m_passEnc[pidx];
-            if (passWorker)
-                passWorker->close();
-        }
-    }
-
     void AbrEncoder::destroy()
     {
-        closeEncoder();
         x265_cleanup(); /* Free library singletons */
         for (uint8_t pass = 0; pass < m_numEncodes; pass++)
         {
             for (uint32_t index = 0; index < m_queueSize; index++)
             {
+                X265_FREE(m_inputPicBuffer[pass][index]->planes[0]);
                 x265_picture_free(m_inputPicBuffer[pass][index]);
             }
+
             X265_FREE(m_inputPicBuffer[pass]);
             X265_FREE(m_analysisBuffer[pass]);
+            X265_FREE(m_readFlag[pass]);
             delete[] m_picIdxReadCnt[pass];
             delete[] m_analysisWrite[pass];
             delete[] m_analysisRead[pass];
             m_passEnc[pass]->destroy();
+            delete m_passEnc[pass];
         }
         X265_FREE(m_inputPicBuffer);
         X265_FREE(m_analysisBuffer);
@@ -211,13 +150,13 @@ namespace X265_NS {
         m_parent = parent;
         if(!(m_cliopt.enableScaler && m_id))
             m_input = m_cliopt.input;
-        m_param = x265_param_alloc();
-        x265_copy_params(m_param, cliopt.param);
+        m_param = cliopt.param;
         m_inputOver = false;
         m_lastIdx = -1;
         m_encoder = NULL;
         m_scaler = NULL;
         m_reader = NULL;
+        m_ret = 0;
     }
 
     int PassEncoder::init(int &result)
@@ -245,24 +184,22 @@ namespace X265_NS {
             }
         }
 
-        if (m_cliopt.zoneFile)
-        {
-            if (!m_cliopt.parseZoneFile())
-            {
-                x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile\n");
-                fclose(m_cliopt.zoneFile);
-                m_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 */
 
         if (m_param)
             m_encoder = m_cliopt.api->encoder_open(m_param);
         if (!m_encoder)
         {
             x265_log(NULL, X265_LOG_ERROR, "x265_encoder_open() failed for Enc, \n");
+            m_ret = 2;
             return -1;
         }
+
+        /* get the encoder parameters post-initialization */
         m_cliopt.api->encoder_parameters(m_encoder, m_param);
+
         return 1;
     }
 
@@ -272,15 +209,13 @@ namespace X265_NS {
 
         m_param->confWinBottomOffset = m_param->confWinRightOffset = 0;
 
-        m_isAnalysisSave = m_cliopt.saveLevel ? true : false;
-        m_isAnalysisLoad = m_cliopt.loadLevel ? true : false;
         m_param->analysisLoadReuseLevel = m_cliopt.loadLevel;
         m_param->analysisSaveReuseLevel = m_cliopt.saveLevel;
-        m_param->analysisSave = m_isAnalysisSave ? "save.dat" : NULL;
-        m_param->analysisLoad = m_isAnalysisLoad ? "load.dat" : NULL;
+        m_param->analysisSave = m_cliopt.saveLevel ? "save.dat" : NULL;
+        m_param->analysisLoad = m_cliopt.loadLevel ? "load.dat" : NULL;
         m_param->bUseAnalysisFile = 0;
 
-        if (m_isAnalysisLoad)
+        if (m_cliopt.loadLevel)
         {
             x265_param *refParam = m_parent->m_passEnc[m_cliopt.refId]->m_param;
 
@@ -460,7 +395,7 @@ ret:
         int ipread = m_parent->m_picReadCnt[m_id].get();
         int ipwrite = m_parent->m_picWriteCnt[m_id].get();
 
-        bool isAbrLoad = m_isAnalysisLoad && (m_parent->m_numEncodes > 1);
+        bool isAbrLoad = m_cliopt.loadLevel && (m_parent->m_numEncodes > 1);
         while (!m_inputOver && (ipread == ipwrite))
         {
             ipwrite = m_parent->m_picWriteCnt[m_id].waitForChange(ipwrite);
@@ -542,7 +477,7 @@ ret:
             pic->pts = srcPic->pts;
             pic->dts = srcPic->dts;
             pic->reorderedPts = srcPic->reorderedPts;
-            pic->poc = srcPic->poc;
+            pic->width = srcPic->width;
             pic->analysisData = srcPic->analysisData;
             pic->userSEI = srcPic->userSEI;
             pic->stride[0] = srcPic->stride[0];
@@ -561,215 +496,273 @@ ret:
 
     void PassEncoder::threadMain()
     {
+        THREAD_NAME("PassEncoder", m_id);
+
+        while (m_threadActive)
+        {
 
 #if ENABLE_LIBVMAF
-        x265_vmaf_data* vmafdata = cliopt.vmafData;
+            x265_vmaf_data* vmafdata = m_cliopt.vmafData;
 #endif
-        /* This allows muxers to modify bitstream format */
-        m_cliopt.output->setParam(m_param);
-        const x265_api* api = m_cliopt.api;
-        ReconPlay* reconPlay = NULL;
-        if (m_cliopt.reconPlayCmd)
-            reconPlay = new ReconPlay(m_cliopt.reconPlayCmd, *m_param);
-
-        if (signal(SIGINT, sigint_handler) == SIG_ERR)
-            x265_log(m_param, X265_LOG_ERROR, "Unable to register CTRL+C handler: %s\n", strerror(errno));
+            /* This allows muxers to modify bitstream format */
+            m_cliopt.output->setParam(m_param);
+            const x265_api* api = m_cliopt.api;
+            ReconPlay* reconPlay = NULL;
+            if (m_cliopt.reconPlayCmd)
+                reconPlay = new ReconPlay(m_cliopt.reconPlayCmd, *m_param);
+            char* profileName = m_cliopt.encName ? m_cliopt.encName : (char *)"x265";
 
-        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 = m_cliopt.output->needPTS() ? new std::priority_queue<int64_t>() : NULL;
-        x265_picture *pic_recon = (m_cliopt.recon || m_param->analysisSave || m_param->analysisLoad || pts_queue || reconPlay || m_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 inputPicNum = 1;
-        x265_picture picField1, picField2;
-        x265_analysis_data* analysisInfo = (x265_analysis_data*)(&pic_out.analysisData);
-        bool isAbrSave = m_isAnalysisSave && (m_parent->m_numEncodes > 1);
-
-        if (!m_param->bRepeatHeaders && !m_param->bEnableSvtHevc)
-        {
-            if (api->encoder_headers(m_encoder, &p_nal, &nal) < 0)
+            if (m_cliopt.zoneFile)
             {
-                x265_log(m_param, X265_LOG_ERROR, "Failure generating stream headers %d\n", m_id);
-                goto fail;
-            }
-            else
-                m_cliopt.totalbytes += m_cliopt.output->writeHeaders(p_nal, nal);
-        }
-
-        if (m_param->bField && m_param->interlaceMode)
-        {
-            api->picture_init(m_param, &picField1);
-            api->picture_init(m_param, &picField2);
-            // return back the original height of input
-            m_param->sourceHeight *= 2;
-            api->picture_init(m_param, &pic_orig);
-        }
-        else
-            api->picture_init(m_param, &pic_orig);
-
-        if (m_param->dolbyProfile && m_cliopt.dolbyVisionRpu)
-        {
-            rpuPayload = X265_MALLOC(uint8_t, 1024);
-            pic_in->rpu.payload = rpuPayload;
-            if (pic_in->rpu.payload)
-                bDolbyVisionRPU = true;
-        }
-
-        if (m_cliopt.bDither)
-        {
-            errorBuf = X265_MALLOC(int16_t, m_param->sourceWidth + 1);
-            if (errorBuf)
-                memset(errorBuf, 0, (m_param->sourceWidth + 1) * sizeof(int16_t));
-            else
-                m_cliopt.bDither = false;
-        }
-
-        // main encoder loop
-        while (pic_in && !b_ctrl_c)
-        {
-            pic_orig.poc = (m_param->bField && m_param->interlaceMode) ? inFrameCount * 2 : inFrameCount;
-            if (m_cliopt.qpfile)
-            {
-                if (!m_cliopt.parseQPFile(pic_orig))
+                if (!m_cliopt.parseZoneFile())
                 {
-                    x265_log(NULL, X265_LOG_ERROR, "can't parse qpfile for frame %d\n", pic_in->poc);
-                    fclose(m_cliopt.qpfile);
-                    m_cliopt.qpfile = NULL;
+                    x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile in %s\n", profileName);
+                    fclose(m_cliopt.zoneFile);
+                    m_cliopt.zoneFile = NULL;
                 }
             }
 
-            if (m_cliopt.framesToBeEncoded && inFrameCount >= m_cliopt.framesToBeEncoded)
+            if (signal(SIGINT, sigint_handler) == SIG_ERR)
+                x265_log(m_param, X265_LOG_ERROR, "Unable to register CTRL+C handler: %s in %s\n",
+                    strerror(errno), profileName);
+
+            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 = m_cliopt.output->needPTS() ? new std::priority_queue<int64_t>() : NULL;
+            x265_picture *pic_recon = (m_cliopt.recon || m_param->analysisSave || m_param->analysisLoad || pts_queue || reconPlay || m_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 inputPicNum = 1;
+            x265_picture picField1, picField2;
+            x265_analysis_data* analysisInfo = (x265_analysis_data*)(&pic_out.analysisData);
+            bool isAbrSave = m_cliopt.saveLevel && (m_parent->m_numEncodes > 1);
+
+            if (!m_param->bRepeatHeaders && !m_param->bEnableSvtHevc)
             {
-                pic_in = NULL;
-            }
-            else if (readPicture(pic_in))
-                inFrameCount++;
-            else
-                pic_in = NULL;
-
-            if (pic_in)
-            {
-                if (pic_in->bitDepth > m_param->internalBitDepth && m_cliopt.bDither)
+                if (api->encoder_headers(m_encoder, &p_nal, &nal) < 0)
                 {
-                    x265_dither_image(pic_in, m_cliopt.input->getWidth(), m_cliopt.input->getHeight(), errorBuf, m_param->internalBitDepth);
-                    pic_in->bitDepth = m_param->internalBitDepth;
+                    x265_log(m_param, X265_LOG_ERROR, "Failure generating stream headers in %s\n", profileName);
+                    m_ret = 3;
+                    goto fail;
                 }
-                /* Overwrite PTS */
-                pic_in->pts = pic_in->poc;
+                else
+                    m_cliopt.totalbytes += m_cliopt.output->writeHeaders(p_nal, nal);
+            }
 
-                // convert to field
-                if (m_param->bField && m_param->interlaceMode)
+            if (m_param->bField && m_param->interlaceMode)
+            {
+                api->picture_init(m_param, &picField1);
+                api->picture_init(m_param, &picField2);
+                // return back the original height of input
+                m_param->sourceHeight *= 2;
+                api->picture_init(m_param, &pic_orig);
+            }
+            else
+                api->picture_init(m_param, &pic_orig);
+
+            if (m_param->dolbyProfile && m_cliopt.dolbyVisionRpu)
+            {
+                rpuPayload = X265_MALLOC(uint8_t, 1024);
+                pic_in->rpu.payload = rpuPayload;
+                if (pic_in->rpu.payload)
+                    bDolbyVisionRPU = true;
+            }
+
+            if (m_cliopt.bDither)
+            {
+                errorBuf = X265_MALLOC(int16_t, m_param->sourceWidth + 1);
+                if (errorBuf)
+                    memset(errorBuf, 0, (m_param->sourceWidth + 1) * sizeof(int16_t));
+                else
+                    m_cliopt.bDither = false;
+            }
+
+            // main encoder loop
+            while (pic_in && !b_ctrl_c)
+            {
+                pic_orig.poc = (m_param->bField && m_param->interlaceMode) ? inFrameCount * 2 : inFrameCount;
+                if (m_cliopt.qpfile)
                 {
-                    int height = pic_in->height >> 1;
-
-                    int static bCreated = 0;
-                    if (bCreated == 0)
+                    if (!m_cliopt.parseQPFile(pic_orig))
                     {
-                        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;
+                        x265_log(NULL, X265_LOG_ERROR, "can't parse qpfile for frame %d in %s\n",
+                            pic_in->poc, profileName);
+                        fclose(m_cliopt.qpfile);
+                        m_cliopt.qpfile = NULL;
+                    }
+                }
 
-                        size_t fieldFrameSize = (size_t)pic_in->framesize >> 1;
-                        char* field1Buf = X265_MALLOC(char, fieldFrameSize);
-                        char* field2Buf = X265_MALLOC(char, fieldFrameSize);
+                if (m_cliopt.framesToBeEncoded && inFrameCount >= m_cliopt.framesToBeEncoded)
+                    pic_in = NULL;
+                else if (readPicture(pic_in))
+                    inFrameCount++;
+                else
+                    pic_in = NULL;
 
-                        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++)
+                if (pic_in)
+                {
+                    if (pic_in->bitDepth > m_param->internalBitDepth && m_cliopt.bDither)
+                    {
+                        x265_dither_image(pic_in, m_cliopt.input->getWidth(), m_cliopt.input->getHeight(), errorBuf, m_param->internalBitDepth);
+                        pic_in->bitDepth = m_param->internalBitDepth;
+                    }
+                    /* Overwrite PTS */
+                    pic_in->pts = pic_in->poc;
+
+                    // convert to field
+                    if (m_param->bField && m_param->interlaceMode)
+                    {
+                        int height = pic_in->height >> 1;
+
+                        int static bCreated = 0;
+                        if (bCreated == 0)
                         {
-                            picField1.planes[i] = field1Buf + framesize;
-                            picField2.planes[i] = field2Buf + framesize;
+                            bCreated = 1;
+                            inputPicNum = 2;
+                            picField1.fieldNum = 1;
+                            picField2.fieldNum = 2;
 
-                            stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i];
-                            framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[i]));
+                            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);
                         }
-                        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;
+                                }
+                            }
+                        }
                     }
 
-                    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->framesize)
+                    if (bDolbyVisionRPU)
                     {
-                        for (int i = 0; i < x265_cli_csps[pic_in->colorSpace].planes; i++)
+                        if (m_param->bField && m_param->interlaceMode)
                         {
-                            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 (m_cliopt.rpuParser(&picField1) > 0)
+                                goto fail;
+                            if (m_cliopt.rpuParser(&picField2) > 0)
+                                goto fail;
+                        }
+                        else
+                        {
+                            if (m_cliopt.rpuParser(pic_in) > 0)
+                                goto fail;
                         }
                     }
                 }
 
-                if (bDolbyVisionRPU)
+                for (int inputNum = 0; inputNum < inputPicNum; inputNum++)
                 {
-                    if (m_param->bField && m_param->interlaceMode)
+                    x265_picture *picInput = NULL;
+                    if (inputPicNum == 2)
+                        picInput = pic_in ? (inputNum ? &picField2 : &picField1) : NULL;
+                    else
+                        picInput = pic_in;
+
+                    int numEncoded = api->encoder_encode(m_encoder, &p_nal, &nal, picInput, pic_recon);
+
+                    int idx = (inFrameCount - 1) % m_parent->m_queueSize;
+                    m_parent->m_picIdxReadCnt[m_id][idx].incr();
+                    m_parent->m_picReadCnt[m_id].incr();
+                    if (m_cliopt.loadLevel && picInput)
                     {
-                        if (rpuParser(&picField1, m_cliopt.dolbyVisionRpu) > 0)
-                            goto fail;
-                        if (rpuParser(&picField2, m_cliopt.dolbyVisionRpu) > 0)
-                            goto fail;
+                        m_parent->m_analysisReadCnt[m_cliopt.refId].incr();
+                        m_parent->m_analysisRead[m_cliopt.refId][m_lastIdx].incr();
                     }
-                    else
+
+                    if (numEncoded < 0)
                     {
-                        if (rpuParser(pic_in, m_cliopt.dolbyVisionRpu) > 0)
-                            goto fail;
+                        b_ctrl_c = 1;
+                        m_ret = 4;
+                        break;
                     }
+
+                    if (reconPlay && numEncoded)
+                        reconPlay->writePicture(*pic_recon);
+
+                    outFrameCount += numEncoded;
+
+                    if (isAbrSave && numEncoded)
+                    {
+                        copyInfo(analysisInfo);
+                    }
+
+                    if (numEncoded && pic_recon && m_cliopt.recon)
+                        m_cliopt.recon->writePicture(pic_out);
+                    if (nal)
+                    {
+                        m_cliopt.totalbytes += m_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();
+                        }
+                    }
+                    m_cliopt.printStatus(outFrameCount);
                 }
             }
 
-            for (int inputNum = 0; inputNum < inputPicNum; inputNum++)
+            /* Flush the encoder */
+            while (!b_ctrl_c)
             {
-                x265_picture *picInput = NULL;
-                if (inputPicNum == 2)
-                    picInput = pic_in ? (inputNum ? &picField2 : &picField1) : NULL;
-                else
-                    picInput = pic_in;
-
-                int numEncoded = api->encoder_encode(m_encoder, &p_nal, &nal, picInput, pic_recon);
-
-                int idx = (inFrameCount - 1) % m_parent->m_queueSize;
-                m_parent->m_picIdxReadCnt[m_id][idx].incr();
-                m_parent->m_picReadCnt[m_id].incr();
-                if (m_cliopt.loadLevel && picInput)
-                {
-                    m_parent->m_analysisReadCnt[m_cliopt.refId].incr();
-                    m_parent->m_analysisRead[m_cliopt.refId][m_lastIdx].incr();
-                }
-
+                int numEncoded = api->encoder_encode(m_encoder, &p_nal, &nal, NULL, pic_recon);
                 if (numEncoded < 0)
                 {
-                    b_ctrl_c = 1;
+                    m_ret = 4;
                     break;
                 }
 
@@ -777,7 +770,6 @@ ret:
                     reconPlay->writePicture(*pic_recon);
 
                 outFrameCount += numEncoded;
-
                 if (isAbrSave && numEncoded)
                 {
                     copyInfo(analysisInfo);
@@ -795,106 +787,77 @@ ret:
                             pts_queue->pop();
                     }
                 }
-                m_cliopt.printStatus(outFrameCount);
-            }
-        }
-
-        /* Flush the encoder */
-        while (!b_ctrl_c)
-        {
-            int numEncoded = api->encoder_encode(m_encoder, &p_nal, &nal, NULL, pic_recon);
-            if (numEncoded < 0)
-                break;
- 
-            if (reconPlay && numEncoded)
-                reconPlay->writePicture(*pic_recon);
 
-            outFrameCount += numEncoded;
-            if (isAbrSave && numEncoded)
-            {
-                copyInfo(analysisInfo);
-            }
+                m_cliopt.printStatus(outFrameCount);
 
-            if (numEncoded && pic_recon && m_cliopt.recon)
-                m_cliopt.recon->writePicture(pic_out);
-            if (nal)
-            {
-                m_cliopt.totalbytes += m_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();
-                }
+                if (!numEncoded)
+                    break;
             }
 
-            m_cliopt.printStatus(outFrameCount);
-
-            if (!numEncoded)
-                break;
-        }
-
-        if (bDolbyVisionRPU)
-        {
-            if (fgetc(m_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");
-        }
-
-        if (bDolbyVisionRPU)
-        {
-            if (fgetc(m_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 (m_cliopt.bProgress)
-            fprintf(stderr, "%*s\r", 80, " ");
-
-    fail:
-
-        delete reconPlay;
+            if (bDolbyVisionRPU)
+            {
+                if (fgetc(m_cliopt.dolbyVisionRpu) != EOF)
+                    x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU count is greater than frame count in %s\n",
+                        profileName);
+                x265_log(NULL, X265_LOG_INFO, "VES muxing with Dolby Vision RPU file successful in %s\n",
+                    profileName);
+            }
 
-        api->encoder_get_stats(m_encoder, &stats, sizeof(stats));
-        if (m_param->csvfn && !b_ctrl_c)
-#if ENABLE_LIBVMAF
-            api->vmaf_encoder_log(encoder, argc, argv, param, vmafdata);
-#else
-            api->encoder_log(m_encoder, 0, NULL);
-#endif
-
-        int64_t second_largest_pts = 0;
-        int64_t largest_pts = 0;
-
-        m_cliopt.output->closeFile(largest_pts, second_largest_pts);
+            /* clear progress report */
+            if (m_cliopt.bProgress)
+                fprintf(stderr, "%*s\r", 80, " ");
 
-        if (b_ctrl_c)
-            general_log(m_param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",
-                m_cliopt.seek + inFrameCount, stats.encodedPictureCount);
-
-        X265_FREE(errorBuf);
-        X265_FREE(rpuPayload);
+        fail:
 
-        m_threadActive = false;
-        m_parent->m_numActiveEncodes.decr();
-    }
+            delete reconPlay;
 
-    void PassEncoder::close()
-    {
-        const x265_api* api = m_cliopt.api;
-        api->param_free(m_param);
-        api->encoder_close(m_encoder);
+            api->encoder_get_stats(m_encoder, &stats, sizeof(stats));
+            if (m_param->csvfn && !b_ctrl_c)
+#if ENABLE_LIBVMAF
+                api->vmaf_encoder_log(m_encoder, m_cliopt.argCount, m_cliopt.argString, m_cliopt.param, vmafdata);
+#else
+                api->encoder_log(m_encoder, m_cliopt.argCnt, m_cliopt.argString);
+#endif
+            api->encoder_close(m_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;
+            }
+            m_cliopt.output->closeFile(largest_pts, second_largest_pts);
+
+            if (b_ctrl_c)
+                general_log(m_param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d in %s\n",
+                    m_cliopt.seek + inFrameCount, stats.encodedPictureCount, profileName);
+
+            api->param_free(m_param);
+
+            X265_FREE(errorBuf);
+            X265_FREE(rpuPayload);
+
+            m_threadActive = false;
+            m_parent->m_numActiveEncodes.decr();
+        }
     }
 
     void PassEncoder::destroy()
     {
+        stop();
         if (m_reader)
         {
+            m_reader->stop();
             delete m_reader;
         }
         else
         {
+            m_scaler->stop();
             m_scaler->destroy();
             delete m_scaler;
         }
@@ -1107,12 +1070,6 @@ ret:
                 read = m_parentEnc->m_parent->m_picIdxReadCnt[m_id][writeIdx].waitForChange(read);
             }
 
-            if (!m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx])
-            {
-                m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx] = x265_picture_alloc();
-                x265_picture_init(m_parentEnc->m_param, m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx]);
-            }
-
             x265_picture* dest = m_parentEnc->m_parent->m_inputPicBuffer[m_id][writeIdx];
             if (m_input->readPicture(*src))
             {
--- a/source/abrEncApp.h	Mon May 04 11:50:39 2020 +0530
+++ b/source/abrEncApp.h	Wed Apr 15 18:44:54 2020 +0530
@@ -60,7 +60,6 @@ namespace X265_NS {
 
         AbrEncoder(CLIOptions cliopt[], uint8_t numEncodes, int& ret);
         bool allocBuffers();
-        void closeEncoder();
         void destroy();
 
     };
@@ -75,11 +74,6 @@ namespace X265_NS {
         x265_encoder *m_encoder;
         Reader *m_reader;
         Scaler *m_scaler;
-
-        bool m_reqScale;
-        bool m_isScaled;
-        bool m_isAnalysisSave;
-        bool m_isAnalysisLoad;
         bool m_inputOver;
 
         int m_threadActive;
@@ -98,7 +92,7 @@ namespace X265_NS {
         FILE*    m_zoneFile;
         FILE*    m_dolbyVisionRpu;/* File containing Dolby Vision BL RPU metadata */
 
-
+        int m_ret;
 
         PassEncoder(uint32_t id, CLIOptions cliopt, AbrEncoder *parent);
         int init(int &result);
@@ -108,7 +102,6 @@ namespace X265_NS {
         void copyInfo(x265_analysis_data *src);
 
         bool readPicture(x265_picture*);
-        void close();
         void destroy();
 
     private:
--- a/source/x265.cpp	Mon May 04 11:50:39 2020 +0530
+++ b/source/x265.cpp	Wed Apr 15 18:44:54 2020 +0530
@@ -29,11 +29,6 @@
 #include "x265cli.h"
 #include "abrEncApp.h"
 
-#include "input/input.h"
-#include "output/output.h"
-#include "output/reconplay.h"
-#include "svt.h"
-
 #if HAVE_VLD
 /* Visual Leak Detector */
 #include <vld.h>
@@ -50,16 +45,12 @@
 
 using namespace X265_NS;
 
+#define X265_HEAD_ENTRIES 3
+
 #ifdef _WIN32
 #define strdup _strdup
 #endif
 
-/* Ctrl-C handler */
-static volatile sig_atomic_t b_ctrl_c /* = 0 */;
-
-#define START_CODE 0x00000001
-#define START_CODE_BYTES 4
-
 #ifdef _WIN32
 /* Copy of x264 code, which allows for Unicode characters in the command line.
  * Retrieve command line arguments as UTF-8. */
@@ -97,7 +88,7 @@ static int get_argv_utf8(int *argc_ptr, 
  * Returns true if abr-config file is present. Returns 
  * false otherwise */
 
-static bool IsAbrLadder(int argc, char **argv, FILE **abrConfig)
+static bool checkAbrLadder(int argc, char **argv, FILE **abrConfig)
 {
     for (optind = 0;;)
     {
@@ -156,77 +147,64 @@ static uint8_t getNumAbrEncodes(FILE* ab
     return numEncodes;
 }
 
-#define X265_HEAD_ENTRIES 3
-
-static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[])
+static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[], uint8_t numEncodes)
 {
     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);
 
     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";
+        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 argc = 0;
+        char **argv = (char**)malloc(256 * sizeof(char *));
+        // Adding a dummy string to avoid file parsing error
+        argv[argc++] = (char *)"x265";
 
-            /* 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;
+        /* 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]);
-            }
+        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, " ");
-            }
-            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;
+        char* token = strtok(start, " ");
+        while (token)
+        {
+            argv[argc++] = token;
+            token = strtok(NULL, " ");
+        }
+        argv[argc] = NULL;
+        if (cliopt[i].parse(argc++, argv))
+        {
+            cliopt[i].destroy();
+            if (cliopt[i].api)
+                cliopt[i].api->param_free(cliopt[i].param);
+            exit(1);
         }
     }
     return true;
@@ -291,7 +269,7 @@ int main(int argc, char **argv)
 
     uint8_t numEncodes = 1;
     FILE *abrConfig = NULL;
-    bool isAbrLadder = IsAbrLadder(argc, argv, &abrConfig);
+    bool isAbrLadder = checkAbrLadder(argc, argv, &abrConfig);
 
     if (isAbrLadder)
         numEncodes = getNumAbrEncodes(abrConfig);
@@ -300,12 +278,12 @@ int main(int argc, char **argv)
 
     if (isAbrLadder)
     {
-        if(!parseAbrConfig(abrConfig, cliopt))
+        if (!parseAbrConfig(abrConfig, cliopt, numEncodes))
             exit(1);
-        if(!setRefContext(cliopt, numEncodes))
+        if (!setRefContext(cliopt, numEncodes))
             exit(1);
     }
-    else if(cliopt[0].parse(argc, argv))
+    else if (cliopt[0].parse(argc, argv))
     {
         cliopt[0].destroy();
         if (cliopt[0].api)
@@ -320,12 +298,27 @@ int main(int argc, char **argv)
     while (threadsActive)
     {
         threadsActive = abrEnc->m_numActiveEncodes.waitForChange(threadsActive);
+        for (uint8_t idx = 0; idx < numEncodes; idx++)
+        {
+            if (abrEnc->m_passEnc[idx]->m_ret)
+            {
+                if (isAbrLadder)
+                    x265_log(NULL, X265_LOG_INFO, "Error generating ABR-ladder \n");
+                ret = abrEnc->m_passEnc[idx]->m_ret;
+                threadsActive = 0;
+                break;
+            }
+        }
     }
 
     abrEnc->destroy();
+    delete abrEnc;
+
     for (uint8_t idx = 0; idx < numEncodes; idx++)
         cliopt[idx].destroy();
 
+    delete[] cliopt;
+
     SetConsoleTitle(orgConsoleTitle);
     SetThreadExecutionState(ES_CONTINUOUS);
 
--- a/source/x265cli.cpp	Mon May 04 11:50:39 2020 +0530
+++ b/source/x265cli.cpp	Wed Apr 15 18:44:54 2020 +0530
@@ -27,6 +27,9 @@
 
 #include "x265cli.h"
 
+#define START_CODE 0x00000001
+#define START_CODE_BYTES 4
+
 #ifdef __cplusplus
 namespace X265_NS {
 #endif
@@ -532,6 +535,8 @@ namespace X265_NS {
         const char *tune = NULL;
         const char *profile = NULL;
         int svtEnabled = 0;
+        argCnt = argc;
+        argString = argv;
 
         if (argc <= 1)
         {
@@ -992,6 +997,58 @@ namespace X265_NS {
         return 1;
     }
 
+    /* Parse the RPU file and extract the RPU corresponding to the current picture
+    * and fill the rpu field of the input picture */
+    int CLIOptions::rpuParser(x265_picture * pic)
+    {
+        uint8_t byteVal;
+        uint32_t code = 0;
+        int bytesRead = 0;
+        pic->rpu.payloadSize = 0;
+
+        if (!pic->pts)
+        {
+            while (bytesRead++ < 4 && fread(&byteVal, sizeof(uint8_t), 1, dolbyVisionRpu))
+                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, dolbyVisionRpu))
+        {
+            code = (code << 8) | byteVal;
+            if (bytesRead++ < 3)
+                continue;
+            if (bytesRead >= 1024)
+            {
+                x265_log(NULL, X265_LOG_ERROR, "Invalid Dolby Vision RPU size in POC %d\n", pic->pts);
+                return 1;
+            }
+
+            if (code != START_CODE)
+                pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;
+            else
+                return 0;
+        }
+
+        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++)
+        {
+            pic->rpu.payload[pic->rpu.payloadSize++] = (code >> (3 * 8)) & 0xFF;
+            code = (code << 8);
+        }
+        if (!pic->rpu.payloadSize)
+            x265_log(NULL, X265_LOG_WARNING, "Dolby Vision RPU not found for POC %d\n", pic->pts);
+        return 0;
+    }
+
 #ifdef __cplusplus
 }
 #endif
\ No newline at end of file
--- a/source/x265cli.h	Mon May 04 11:50:39 2020 +0530
+++ b/source/x265cli.h	Wed Apr 15 18:44:54 2020 +0530
@@ -378,7 +378,7 @@ static const struct option long_options[
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 }
-    };
+};
 
     struct CLIOptions
     {
@@ -401,6 +401,9 @@ static const struct option long_options[
         int64_t startTime;
         int64_t prevUpdateTime;
 
+        int argCnt;
+        char** argString;
+
         /* ABR ladder settings */
         bool enableScaler;
         char*    encName;
@@ -411,7 +414,6 @@ static const struct option long_options[
         uint32_t saveLevel;
         uint32_t numRefs;
 
-
         /* in microseconds */
         static const int UPDATE_INTERVAL = 250000;
         CLIOptions()
@@ -434,11 +436,14 @@ static const struct option long_options[
             prevUpdateTime = 0;
             bDither = false;
             enableScaler = false;
+            encName = NULL;
+            reuseName = NULL;
             encId = 0;
             refId = -1;
             loadLevel = 0;
             saveLevel = 0;
             numRefs = 0;
+            argCnt = 0;
         }
 
         void destroy();
@@ -447,6 +452,7 @@ static const struct option long_options[
         bool parseZoneParam(int argc, char **argv, x265_param* globalParam, int zonefileCount);
         bool parseQPFile(x265_picture &pic_org);
         bool parseZoneFile();
+        int rpuParser(x265_picture * pic);
     };
 #ifdef __cplusplus
 }