# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1586956494 -19800 # Wed Apr 15 18:44:54 2020 +0530 # Node ID 303ff9e4546d0052e7a4d359323f0aca84eedd68 # Parent 193db4916b9f3fb0a0f97d78229c245e7dda1928 Cleanup
diff -r 193db4916b9f -r 303ff9e4546d source/abrEncApp.cpp --- 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } - 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 @@ 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 @@ 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 @@ 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 @@ 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); + } + + 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); - // convert to field - if (m_param->bField && m_param->interlaceMode) + 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; + 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; + } + } + + if (m_cliopt.framesToBeEncoded && inFrameCount >= m_cliopt.framesToBeEncoded) + pic_in = NULL; + else if (readPicture(pic_in)) + inFrameCount++; + else + pic_in = NULL; - 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; + 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; - size_t fieldFrameSize = (size_t)pic_in->framesize >> 1; - char* field1Buf = X265_MALLOC(char, fieldFrameSize); - char* field2Buf = X265_MALLOC(char, fieldFrameSize); + int static bCreated = 0; + if (bCreated == 0) + { + bCreated = 1; + inputPicNum = 2; + picField1.fieldNum = 1; + picField2.fieldNum = 2; + + picField1.bitDepth = picField2.bitDepth = pic_in->bitDepth; + picField1.colorSpace = picField2.colorSpace = pic_in->colorSpace; + picField1.height = picField2.height = pic_in->height >> 1; + picField1.framesize = picField2.framesize = pic_in->framesize >> 1; + + size_t fieldFrameSize = (size_t)pic_in->framesize >> 1; + char* field1Buf = X265_MALLOC(char, fieldFrameSize); + char* field2Buf = X265_MALLOC(char, fieldFrameSize); - int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0]; - uint64_t framesize = stride * (height >> x265_cli_csps[pic_in->colorSpace].height[0]); - picField1.planes[0] = field1Buf; - picField2.planes[0] = field2Buf; - for (int i = 1; i < x265_cli_csps[pic_in->colorSpace].planes; i++) + int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0]; + uint64_t framesize = stride * (height >> x265_cli_csps[pic_in->colorSpace].height[0]); + picField1.planes[0] = field1Buf; + picField2.planes[0] = field2Buf; + for (int i = 1; i < x265_cli_csps[pic_in->colorSpace].planes; i++) + { + picField1.planes[i] = field1Buf + framesize; + picField2.planes[i] = field2Buf + framesize; + + stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i]; + framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[i])); + } + assert(framesize == picField1.framesize); + } + + picField1.pts = picField1.poc = pic_in->poc; + picField2.pts = picField2.poc = pic_in->poc + 1; + + picField1.userSEI = picField2.userSEI = pic_in->userSEI; + + //if (pic_in->userData) + //{ + // // Have to handle userData here + //} + + if (pic_in->framesize) { - picField1.planes[i] = field1Buf + framesize; - picField2.planes[i] = field2Buf + 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]; - stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i]; - framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[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; + } + } } - 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->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) + { + m_parent->m_analysisReadCnt[m_cliopt.refId].incr(); + m_parent->m_analysisRead[m_cliopt.refId][m_lastIdx].incr(); + } + + if (numEncoded < 0) { - if (rpuParser(&picField1, m_cliopt.dolbyVisionRpu) > 0) - goto fail; - if (rpuParser(&picField2, 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); } - else + + if (numEncoded && pic_recon && m_cliopt.recon) + m_cliopt.recon->writePicture(pic_out); + if (nal) { - if (rpuParser(pic_in, m_cliopt.dolbyVisionRpu) > 0) - goto fail; + 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 @@ reconPlay->writePicture(*pic_recon); outFrameCount += numEncoded; - if (isAbrSave && numEncoded) { copyInfo(analysisInfo); @@ -795,106 +787,77 @@ 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); + if (!numEncoded) + break; } - if (numEncoded && pic_recon && m_cliopt.recon) - m_cliopt.recon->writePicture(pic_out); - if (nal) + if (bDolbyVisionRPU) { - 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 (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); } - m_cliopt.printStatus(outFrameCount); - - if (!numEncoded) - break; - } + /* clear progress report */ + if (m_cliopt.bProgress) + fprintf(stderr, "%*s\r", 80, " "); - 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"); - } + 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\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; + 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); - 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); + 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\n", - m_cliopt.seek + inFrameCount, stats.encodedPictureCount); + 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); - X265_FREE(errorBuf); - X265_FREE(rpuPayload); + api->param_free(m_param); - m_threadActive = false; - m_parent->m_numActiveEncodes.decr(); - } + X265_FREE(errorBuf); + X265_FREE(rpuPayload); - void PassEncoder::close() - { - const x265_api* api = m_cliopt.api; - api->param_free(m_param); - api->encoder_close(m_encoder); + 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 @@ 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)) { diff -r 193db4916b9f -r 303ff9e4546d source/abrEncApp.h --- 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 @@ AbrEncoder(CLIOptions cliopt[], uint8_t numEncodes, int& ret); bool allocBuffers(); - void closeEncoder(); void destroy(); }; @@ -75,11 +74,6 @@ 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 @@ 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 @@ void copyInfo(x265_analysis_data *src); bool readPicture(x265_picture*); - void close(); void destroy(); private: diff -r 193db4916b9f -r 303ff9e4546d source/x265.cpp --- 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -r 193db4916b9f -r 303ff9e4546d source/x265cli.cpp --- 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 @@ const char *tune = NULL; const char *profile = NULL; int svtEnabled = 0; + argCnt = argc; + argString = argv; if (argc <= 1) { @@ -992,6 +997,58 @@ 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 diff -r 193db4916b9f -r 303ff9e4546d source/x265cli.h --- 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 @@ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } - }; +}; struct CLIOptions { @@ -401,6 +401,9 @@ int64_t startTime; int64_t prevUpdateTime; + int argCnt; + char** argString; + /* ABR ladder settings */ bool enableScaler; char* encName; @@ -411,7 +414,6 @@ uint32_t saveLevel; uint32_t numRefs; - /* in microseconds */ static const int UPDATE_INTERVAL = 250000; CLIOptions() @@ -434,11 +436,14 @@ 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 @@ 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 }
# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1586956494 -19800 # Wed Apr 15 18:44:54 2020 +0530 # Node ID 303ff9e4546d0052e7a4d359323f0aca84eedd68 # Parent 193db4916b9f3fb0a0f97d78229c245e7dda1928 Cleanup diff -r 193db4916b9f -r 303ff9e4546d source/abrEncApp.cpp --- 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } - 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 @@ 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 @@ 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 @@ 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 @@ 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); + } + + 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); - // convert to field - if (m_param->bField && m_param->interlaceMode) + 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; + 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; + } + } + + if (m_cliopt.framesToBeEncoded && inFrameCount >= m_cliopt.framesToBeEncoded) + pic_in = NULL; + else if (readPicture(pic_in)) + inFrameCount++; + else + pic_in = NULL; - 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; + 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; - size_t fieldFrameSize = (size_t)pic_in->framesize >> 1; - char* field1Buf = X265_MALLOC(char, fieldFrameSize); - char* field2Buf = X265_MALLOC(char, fieldFrameSize); + int static bCreated = 0; + if (bCreated == 0) + { + bCreated = 1; + inputPicNum = 2; + picField1.fieldNum = 1; + picField2.fieldNum = 2; + + picField1.bitDepth = picField2.bitDepth = pic_in->bitDepth; + picField1.colorSpace = picField2.colorSpace = pic_in->colorSpace; + picField1.height = picField2.height = pic_in->height >> 1; + picField1.framesize = picField2.framesize = pic_in->framesize >> 1; + + size_t fieldFrameSize = (size_t)pic_in->framesize >> 1; + char* field1Buf = X265_MALLOC(char, fieldFrameSize); + char* field2Buf = X265_MALLOC(char, fieldFrameSize); - int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0]; - uint64_t framesize = stride * (height >> x265_cli_csps[pic_in->colorSpace].height[0]); - picField1.planes[0] = field1Buf; - picField2.planes[0] = field2Buf; - for (int i = 1; i < x265_cli_csps[pic_in->colorSpace].planes; i++) + int stride = picField1.stride[0] = picField2.stride[0] = pic_in->stride[0]; + uint64_t framesize = stride * (height >> x265_cli_csps[pic_in->colorSpace].height[0]); + picField1.planes[0] = field1Buf; + picField2.planes[0] = field2Buf; + for (int i = 1; i < x265_cli_csps[pic_in->colorSpace].planes; i++) + { + picField1.planes[i] = field1Buf + framesize; + picField2.planes[i] = field2Buf + framesize; + + stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i]; + framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[i])); + } + assert(framesize == picField1.framesize); + } + + picField1.pts = picField1.poc = pic_in->poc; + picField2.pts = picField2.poc = pic_in->poc + 1; + + picField1.userSEI = picField2.userSEI = pic_in->userSEI; + + //if (pic_in->userData) + //{ + // // Have to handle userData here + //} + + if (pic_in->framesize) { - picField1.planes[i] = field1Buf + framesize; - picField2.planes[i] = field2Buf + 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]; - stride = picField1.stride[i] = picField2.stride[i] = pic_in->stride[i]; - framesize += (stride * (height >> x265_cli_csps[pic_in->colorSpace].height[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; + } + } } - 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->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) + { + m_parent->m_analysisReadCnt[m_cliopt.refId].incr(); + m_parent->m_analysisRead[m_cliopt.refId][m_lastIdx].incr(); + } + + if (numEncoded < 0) { - if (rpuParser(&picField1, m_cliopt.dolbyVisionRpu) > 0) - goto fail; - if (rpuParser(&picField2, 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); } - else + + if (numEncoded && pic_recon && m_cliopt.recon) + m_cliopt.recon->writePicture(pic_out); + if (nal) { - if (rpuParser(pic_in, m_cliopt.dolbyVisionRpu) > 0) - goto fail; + 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 @@ reconPlay->writePicture(*pic_recon); outFrameCount += numEncoded; - if (isAbrSave && numEncoded) { copyInfo(analysisInfo); @@ -795,106 +787,77 @@ 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); + if (!numEncoded) + break; } - if (numEncoded && pic_recon && m_cliopt.recon) - m_cliopt.recon->writePicture(pic_out); - if (nal) + if (bDolbyVisionRPU) { - 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 (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); } - m_cliopt.printStatus(outFrameCount); - - if (!numEncoded) - break; - } + /* clear progress report */ + if (m_cliopt.bProgress) + fprintf(stderr, "%*s\r", 80, " "); - 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"); - } + 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\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; + 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); - 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); + 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\n", - m_cliopt.seek + inFrameCount, stats.encodedPictureCount); + 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); - X265_FREE(errorBuf); - X265_FREE(rpuPayload); + api->param_free(m_param); - m_threadActive = false; - m_parent->m_numActiveEncodes.decr(); - } + X265_FREE(errorBuf); + X265_FREE(rpuPayload); - void PassEncoder::close() - { - const x265_api* api = m_cliopt.api; - api->param_free(m_param); - api->encoder_close(m_encoder); + 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 @@ 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)) { diff -r 193db4916b9f -r 303ff9e4546d source/abrEncApp.h --- 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 @@ AbrEncoder(CLIOptions cliopt[], uint8_t numEncodes, int& ret); bool allocBuffers(); - void closeEncoder(); void destroy(); }; @@ -75,11 +74,6 @@ 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 @@ 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 @@ void copyInfo(x265_analysis_data *src); bool readPicture(x265_picture*); - void close(); void destroy(); private: diff -r 193db4916b9f -r 303ff9e4546d source/x265.cpp --- 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -r 193db4916b9f -r 303ff9e4546d source/x265cli.cpp --- 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 @@ const char *tune = NULL; const char *profile = NULL; int svtEnabled = 0; + argCnt = argc; + argString = argv; if (argc <= 1) { @@ -992,6 +997,58 @@ 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 diff -r 193db4916b9f -r 303ff9e4546d source/x265cli.h --- 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 @@ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } - }; +}; struct CLIOptions { @@ -401,6 +401,9 @@ int64_t startTime; int64_t prevUpdateTime; + int argCnt; + char** argString; + /* ABR ladder settings */ bool enableScaler; char* encName; @@ -411,7 +414,6 @@ uint32_t saveLevel; uint32_t numRefs; - /* in microseconds */ static const int UPDATE_INTERVAL = 250000; CLIOptions() @@ -434,11 +436,14 @@ 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 @@ 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 }
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel