From 4bcbb0c2ce94f2fbd2be90e7ead3a7abb0662dfc Mon Sep 17 00:00:00 2001 From: "SUN, Jing" Date: Tue, 3 Sep 2019 11:14:28 +0800 Subject: [PATCH] Add the "-thread-count" parameter support (#330) Signed-off-by: Jing Sun --- Config/Sample.cfg | 1 + Docs/svt-hevc_encoder_user_guide.md | 4 ++ Source/API/EbApi.h | 5 +++ Source/App/EbAppConfig.c | 4 ++ Source/App/EbAppConfig.h | 17 ++++---- Source/App/EbAppContext.c | 16 +++++++- Source/Lib/Codec/EbEncHandle.c | 39 +++++++++++++++---- ...hevc-add-libsvt-hevc-encoder-wrapper.patch | 30 +++++++++++--- 8 files changed, 92 insertions(+), 24 deletions(-) diff --git a/Config/Sample.cfg b/Config/Sample.cfg index a7c7b8632..4e6f53eda 100644 --- a/Config/Sample.cfg +++ b/Config/Sample.cfg @@ -118,3 +118,4 @@ NaluFile : Nalu.txt # SEI message. CEA 608/7 AsmType : 1 # Assembly instruction set (0: non-AVX2, 1: up to AVX512 (Default: set based on platform capabilities)) TargetSocket : -1 # For dual socket systems, this can specify which socket the encoder runs on (-1=Both Sockets, 0=Socket 0, 1=Socket 1) LogicalProcessors : 0 # The number of logical processor which encoder threads run on [0-N] (N is maximum number of logical processor) +ThreadCount : 0 # The number of threads to get created and run [0-N] (0: Auto, 96: Min) diff --git a/Docs/svt-hevc_encoder_user_guide.md b/Docs/svt-hevc_encoder_user_guide.md index b0574d12e..7390b92d4 100644 --- a/Docs/svt-hevc_encoder_user_guide.md +++ b/Docs/svt-hevc_encoder_user_guide.md @@ -231,6 +231,9 @@ This token sets the number of logical processors which the encoder threads run o For dual socket systems, this token specific which socket the encoder runs on. +>-thread-count integer **[Optional]** + +This token sets the number of threads to get created and run. For example, the following command encodes 100 frames of the YUV video sequence into the bin bit stream file. The picture is 1920 luma pixels wide and 1080 pixels high using the Sample.cfg configuration. The QP equals 30 and the md5 checksum is not included in the bit stream. @@ -313,6 +316,7 @@ The encoder parameters present in the Sample.cfg file are listed in this table b | **AsmType** | -asm | [0,1] | 1 | Assembly instruction set
(0: C Only, 1: Automatically select highest assembly instruction set supported) | | **LogicalProcessors** | -lp | [0, total number of logical processor] | 0 | The number of logical processor which encoder threads run on.Refer to Appendix A.2 | | **TargetSocket** | -ss | [-1,1] | -1 | For dual socket systems, this can specify which socket the encoder runs on.Refer to Appendix A.2 | +| **ThreadCount** | -thread-count | [0,N] | 0 | The number of threads to get created and run, 0 = AUTO | | **SwitchThreadsToRtPriority** | -rt | [0,1] | 1 | Enables or disables threads to real time priority, 0 = OFF, 1 = ON (only works on Linux) | | **FPSInVPS** | -fpsinvps | [0,1] | 1 | Enables or disables the VPS timing info, 0 = OFF, 1 = ON | | **TileRowCount** | -tile_row_cnt | [1,16] | 1 | Tile count in the Row | diff --git a/Source/API/EbApi.h b/Source/API/EbApi.h index 01d0cee69..597d7fea1 100644 --- a/Source/API/EbApi.h +++ b/Source/API/EbApi.h @@ -18,6 +18,9 @@ extern "C" { #define EB_HME_SEARCH_AREA_COLUMN_MAX_COUNT 2 #define EB_HME_SEARCH_AREA_ROW_MAX_COUNT 2 +#define EB_THREAD_COUNT_MIN_CORE 48 +#define EB_THREAD_COUNT_FACTOR 2 + #ifdef _WIN32 #define EB_API __declspec(dllexport) #else @@ -560,6 +563,8 @@ typedef struct EB_H265_ENC_CONFIGURATION * Default is 1. */ uint8_t switchThreadsToRtPriority; + /* The total number of working threads to create. */ + uint32_t threadCount; // ASM Type diff --git a/Source/App/EbAppConfig.c b/Source/App/EbAppConfig.c index 83cb788fa..f7ff5b592 100644 --- a/Source/App/EbAppConfig.c +++ b/Source/App/EbAppConfig.c @@ -99,6 +99,7 @@ #define ASM_TYPE_TOKEN "-asm" // no Eval #define THREAD_MGMNT "-lp" #define TARGET_SOCKET "-ss" +#define THREAD_COUNT "-thread-count" #define SWITCHTHREADSTOREALTIME_TOKEN "-rt" #define FPSINVPS_TOKEN "-fpsinvps" #define UNRESTRICTED_MOTION_VECTOR "-umv" @@ -265,6 +266,7 @@ static void SetAsmType (const char *value, EbConfig_t * static void SetLogicalProcessors (const char *value, EbConfig_t *cfg) {cfg->logicalProcessors = (uint32_t)strtoul(value, NULL, 0);}; static void SetTargetSocket (const char *value, EbConfig_t *cfg) {cfg->targetSocket = (int32_t)strtol(value, NULL, 0);}; static void SetSwitchThreadsToRtPriority (const char *value, EbConfig_t *cfg) {cfg->switchThreadsToRtPriority = (EB_BOOL)strtol(value, NULL, 0);}; +static void SetThreadCount (const char *value, EbConfig_t *cfg) {cfg->threadCount = (uint32_t)strtoul(value, NULL, 0); }; static void SetFpsInVps (const char *value, EbConfig_t *cfg) {cfg->fpsInVps = (EB_BOOL)strtol(value, NULL, 0);}; static void SetUnrestrictedMotionVector (const char *value, EbConfig_t *cfg) {cfg->unrestrictedMotionVector = (EB_BOOL)strtol(value, NULL, 0);}; @@ -415,6 +417,7 @@ config_entry_t config_entry[] = { { SINGLE_INPUT, ASM_TYPE_TOKEN, "AsmType", SetAsmType }, { SINGLE_INPUT, TARGET_SOCKET, "TargetSocket", SetTargetSocket }, { SINGLE_INPUT, THREAD_MGMNT, "LogicalProcessors", SetLogicalProcessors }, + { SINGLE_INPUT, THREAD_COUNT, "ThreadCount", SetThreadCount }, // Termination { SINGLE_INPUT, NULL, NULL, NULL } @@ -557,6 +560,7 @@ void EbConfigCtor(EbConfig_t *configPtr) configPtr->asmType = 1; configPtr->targetSocket = -1; configPtr->logicalProcessors = 0; + configPtr->threadCount = 0; // vbv configPtr->vbvMaxRate = 0; diff --git a/Source/App/EbAppConfig.h b/Source/App/EbAppConfig.h index d6d55b883..1d0038f54 100644 --- a/Source/App/EbAppConfig.h +++ b/Source/App/EbAppConfig.h @@ -376,14 +376,15 @@ typedef struct EbConfig_s /**************************************** * Instance Info ****************************************/ - uint32_t channelId; - uint32_t activeChannelCount; - uint32_t logicalProcessors; - int32_t targetSocket; - EB_BOOL stopEncoder; // to signal CTRL+C Event, need to stop encoding. - - uint64_t processedFrameCount; - uint64_t processedByteCount; + uint32_t channelId; + uint32_t activeChannelCount; + uint32_t logicalProcessors; + int32_t targetSocket; + uint32_t threadCount; + EB_BOOL stopEncoder; // to signal CTRL+C Event, need to stop encoding. + + uint64_t processedFrameCount; + uint64_t processedByteCount; /**************************************** * SEI parameters diff --git a/Source/App/EbAppContext.c b/Source/App/EbAppContext.c index 37106944f..d9dca8632 100644 --- a/Source/App/EbAppContext.c +++ b/Source/App/EbAppContext.c @@ -207,9 +207,21 @@ EB_ERRORTYPE CopyConfigurationParameters( callbackData->ebEncParameters.activeChannelCount = config->activeChannelCount; callbackData->ebEncParameters.logicalProcessors = config->logicalProcessors; callbackData->ebEncParameters.targetSocket = config->targetSocket; + if ((config->threadCount > 0) && (config->threadCount < EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR)) { + callbackData->ebEncParameters.threadCount = EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR; + printf("\nWarning: the thread count %u is set too small and is forced to the min value %u\n", + config->threadCount, callbackData->ebEncParameters.threadCount); + } else { + callbackData->ebEncParameters.threadCount = (config->threadCount + EB_THREAD_COUNT_MIN_CORE - 1) + / EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_MIN_CORE; + if (callbackData->ebEncParameters.threadCount != config->threadCount) + printf("\nInformation: the thread count %u is rounded to %u\n", + config->threadCount, callbackData->ebEncParameters.threadCount); + } + callbackData->ebEncParameters.unrestrictedMotionVector = config->unrestrictedMotionVector; - callbackData->ebEncParameters.bitRateReduction = (uint8_t)config->bitRateReduction; - callbackData->ebEncParameters.improveSharpness = (uint8_t)config->improveSharpness; + callbackData->ebEncParameters.bitRateReduction = (uint8_t)config->bitRateReduction; + callbackData->ebEncParameters.improveSharpness = (uint8_t)config->improveSharpness; callbackData->ebEncParameters.videoUsabilityInfo = config->videoUsabilityInfo; callbackData->ebEncParameters.highDynamicRangeInput = config->highDynamicRangeInput; callbackData->ebEncParameters.accessUnitDelimiter = config->accessUnitDelimiter; diff --git a/Source/Lib/Codec/EbEncHandle.c b/Source/Lib/Codec/EbEncHandle.c index 7a98b08a2..f6ac44419 100644 --- a/Source/Lib/Codec/EbEncHandle.c +++ b/Source/Lib/Codec/EbEncHandle.c @@ -2105,9 +2105,14 @@ void LoadDefaultBufferConfigurationSettings( unsigned int lpCount = GetNumProcessors(); unsigned int coreCount = lpCount; + + unsigned int totalThreadCount; + unsigned int threadUnit; + #if defined(_WIN32) || defined(__linux__) if (sequenceControlSetPtr->staticConfig.targetSocket != -1) coreCount /= numGroups; + if (sequenceControlSetPtr->staticConfig.logicalProcessors != 0) coreCount = sequenceControlSetPtr->staticConfig.logicalProcessors < coreCount ? sequenceControlSetPtr->staticConfig.logicalProcessors: coreCount; @@ -2127,6 +2132,23 @@ void LoadDefaultBufferConfigurationSettings( coreCount = lpCount; #endif + // Thread count computation + if (sequenceControlSetPtr->staticConfig.threadCount != 0) + totalThreadCount = sequenceControlSetPtr->staticConfig.threadCount; + else + totalThreadCount = coreCount * EB_THREAD_COUNT_FACTOR; + + if (totalThreadCount < EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR) { + coreCount = EB_THREAD_COUNT_MIN_CORE; + totalThreadCount = coreCount * EB_THREAD_COUNT_FACTOR; + } + + if (totalThreadCount % EB_THREAD_COUNT_MIN_CORE) { + totalThreadCount = (totalThreadCount + EB_THREAD_COUNT_MIN_CORE - 1) + / EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_MIN_CORE; + } + threadUnit = totalThreadCount / EB_THREAD_COUNT_MIN_CORE; + sequenceControlSetPtr->inputOutputBufferFifoInitCount = inputPic + SCD_LAD; // ME segments @@ -2202,14 +2224,15 @@ void LoadDefaultBufferConfigurationSettings( //#====================== Processes number ====================== sequenceControlSetPtr->totalProcessInitCount = 0; - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->pictureAnalysisProcessInitCount = MAX(15, coreCount / 6); - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->motionEstimationProcessInitCount = MAX(20, coreCount / 3); - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->sourceBasedOperationsProcessInitCount = MAX(3, coreCount / 12); - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->modeDecisionConfigurationProcessInitCount = MAX(3, coreCount / 12); - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->encDecProcessInitCount = MAX(40, coreCount); - sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->entropyCodingProcessInitCount = MAX(3, coreCount / 6); - + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->pictureAnalysisProcessInitCount = threadUnit * 4; + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->motionEstimationProcessInitCount = threadUnit * 8; + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->sourceBasedOperationsProcessInitCount = threadUnit * 2; + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->modeDecisionConfigurationProcessInitCount = threadUnit * 2; + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->entropyCodingProcessInitCount = threadUnit * 4; sequenceControlSetPtr->totalProcessInitCount += 6; // single processes count + sequenceControlSetPtr->totalProcessInitCount += sequenceControlSetPtr->encDecProcessInitCount = + totalThreadCount - sequenceControlSetPtr->totalProcessInitCount; + SVT_LOG("Number of logical cores available: %u\nNumber of PPCS %u\n", coreCount, inputPic); return; @@ -3238,10 +3261,10 @@ EB_ERRORTYPE EbH265EncInitParameter( // ASM Type configPtr->asmType = 1; - // Channel info configPtr->logicalProcessors = 0; configPtr->targetSocket = -1; + configPtr->threadCount = 0; configPtr->channelId = 0; configPtr->activeChannelCount = 1; diff --git a/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch b/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch index 1ba5dcf09..ec5504485 100644 --- a/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch +++ b/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch @@ -1,4 +1,4 @@ -From 80e3f410d1ad8807bd4a9f4d5cdf7a7b3c5962ce Mon Sep 17 00:00:00 2001 +From 3248aee7fc94304cd5f41afa8dc502d92ae080ef Mon Sep 17 00:00:00 2001 From: Jing Sun Date: Wed, 21 Nov 2018 11:33:04 +0800 Subject: [PATCH 1/1] lavc/svt_hevc: add libsvt hevc encoder wrapper @@ -11,8 +11,8 @@ Signed-off-by: Jing Sun configure | 4 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + - libavcodec/libsvt_hevc.c | 497 +++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 503 insertions(+) + libavcodec/libsvt_hevc.c | 515 +++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 521 insertions(+) create mode 100644 libavcodec/libsvt_hevc.c diff --git a/configure b/configure @@ -77,10 +77,10 @@ index d2f9a39..d8788a7 100644 extern AVCodec ff_libvo_amrwbenc_encoder; diff --git a/libavcodec/libsvt_hevc.c b/libavcodec/libsvt_hevc.c new file mode 100644 -index 0000000..24ab0ff +index 0000000..77eae48 --- /dev/null +++ b/libavcodec/libsvt_hevc.c -@@ -0,0 +1,497 @@ +@@ -0,0 +1,515 @@ +/* +* Scalable Video Technology for HEVC encoder library plugin +* @@ -142,6 +142,7 @@ index 0000000..24ab0ff + int asm_type; + int forced_idr; + int la_depth; ++ int thread_count; +} SvtContext; + +static int error_mapping(EB_ERRORTYPE svt_ret) @@ -282,6 +283,20 @@ index 0000000..24ab0ff + if (svt_enc->la_depth != -1) + param->lookAheadDistance = svt_enc->la_depth; + ++ if ((svt_enc->thread_count > 0) && ++ (svt_enc->thread_count < (EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR))) { ++ param->threadCount = EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR; ++ av_log(avctx, AV_LOG_WARNING, "Thread count is set too small, forced to %"PRId32"\n", ++ param->threadCount); ++ } else if (svt_enc->thread_count % EB_THREAD_COUNT_MIN_CORE) { ++ param->threadCount = (svt_enc->thread_count + EB_THREAD_COUNT_MIN_CORE - 1) ++ / EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_MIN_CORE; ++ av_log(avctx, AV_LOG_DEBUG, "Thread count is rounded to %"PRId32"\n", ++ param->threadCount); ++ } else { ++ param->threadCount = svt_enc->thread_count; ++ } ++ + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) + param->codeVpsSpsPps = 0; + else @@ -525,6 +540,9 @@ index 0000000..24ab0ff + { "sc_detection", "Scene change detection", OFFSET(scd), + AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + ++ { "thread_count", "Number of threads [0: Auto, 96: Min]", OFFSET(thread_count), ++ AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE }, ++ + { "tier", "Set tier (general_tier_flag)", OFFSET(tier), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" }, + { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" }, @@ -565,7 +583,7 @@ index 0000000..24ab0ff + .init = eb_enc_init, + .encode2 = eb_encode_frame, + .close = eb_enc_close, -+ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, ++ .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P,