Mercurial > x265
changeset 12490:878541319ea1 draft
Integrate SVT-HEVC encoder to x265
***
Integrate SVT-HEVC Encoder with X265
-Modified SEI Parameters intraction with SVT-HEVC
author | Radhakrishnan |
---|---|
date | Thu, 14 Feb 2019 11:06:36 +0530 |
parents | dcbec33bfb0f |
children | a41325fc854f |
files | doc/reST/cli.rst doc/reST/index.rst doc/reST/svthevc.rst source/CMakeLists.txt source/cmake/Findsvthevc.cmake source/common/param.cpp source/common/param.h source/encoder/CMakeLists.txt source/encoder/api.cpp source/encoder/encoder.cpp source/encoder/encoder.h source/encoder/level.cpp source/encoder/svt.h source/x265.cpp source/x265.h source/x265cli.h |
diffstat | 16 files changed, 1494 insertions(+-), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/reST/cli.rst Fri Feb 08 16:02:53 2019 +0530 +++ b/doc/reST/cli.rst Thu Feb 14 11:06:36 2019 +0530 @@ -2384,4 +2384,80 @@ Debugging options **CLI ONLY** +SVT-HEVC Encoder Options +======================== +This section lists options which are SVT-HEVC encoder specific. +See section :ref:`svthevc <SvtHevc>` for more details. + +.. option:: --svt, --no-svt + Enable SVT-HEVC encoder if x265 is built with SVT-HEVC library. Default disabled. + +.. option:: --svt-hme, --no-svt-hme + Enable Hierarchical Motion Estimation(HME) in SVT-HEVC. Default enabled. + + **CLI_ONLY** + +.. option:: --svt-search-width <integer> + Search Area Width used during motion estimation. It depends on input resolution. + Values: [1-256] + + **CLI_ONLY** + +.. option:: --svt-search-height <integer> + Search Area Height used during motion estimation. It depends on input resolution. + Values: [1-256] + + **CLI_ONLY** + +.. option:: --svt-compressed-ten-bit-format, --no-svt-compressed-ten-bit-format + In order to reduce the size of input YUV and to increase channel density, SVT-HEVC accetps inputs in compressed-ten-bit-format. The conversion between yuv420p10le and compressed ten bit format is a lossless operation. For more details about the conversion refer `here<https://github.com/intel/SVT-HEVC/blob/master/Docs/SVT-HEVC_Encoder_User_Guide.pdf>'_. + + **CLI_ONLY** + +.. option:: --svt-speed-control, --no-svt-speed-control + Enable speed control functionality to achieve real time encoding speed defined by :option:`--fps`. Default disabled. + + **CLI_ONLY** + +.. option:: --svt-preset-tuner <integer> + SVT-HEVC exposes 13 presets. Presets [3-12] of SVT-HEVC is mapped to x265's presets [placebo-ultrafast]. Ultrafast is mapped to preset(12) of SVT-HEVC, superfast to preset(11), placebo to preset(3) and so on. svt-preset-tuner works only on top of placebo preset and maps to presets (0-2) of SVT-HEVC. + Values: [0-2] + + **CLI_ONLY** + +.. option:: --svt-hierarchical-level <integer> + Enables multiple hierarchical levels in SVT-HEVC. Accepts values in the range [0-3]. + 0 - Flat + 1 - 2-Level Hierarchy + 2 - 3-Level Hierarchy + 3 - 4-Level Hierarchy + + Default: 3 + + **CLI_ONLY** + +.. option:: --svt-base-layer-switch-mode <integer> + Choose type of slices to be in base layer. Accepts values 0,1. + 0 - Use B-frames in the base layer + 1 - Use P-frames in the base layer + + Default: 0 + + **CLI_ONLY** + +.. option:: --svt-pred-struct <integer> + Prediction structure forms the basis in deciding the GOP structure. SVT-HEVC supports Low delay(P/B) and random access prediction structure. In a low delay structure, pictures within a mini-gop can only refer to the previous pictures in display order. In other words, picture with display order N can only refer to pictures of display order lower than N. In random acccess method, pictures can be referenced from both the directions. It accepts values in the range [0-2] + 0 - Low Delay P + 1 - Low Delay B + 2 - Random Access + + Default: 2 + + **CLI_ONLY** + +.. option:: --svt-fps-in-vps, --no-svt-fps-in-vps + Enable sending timing info in VPS. Default disabled. + + **CLI_ONLY** + .. vim: noet
--- a/doc/reST/index.rst Fri Feb 08 16:02:53 2019 +0530 +++ b/doc/reST/index.rst Thu Feb 14 11:06:36 2019 +0530 @@ -9,4 +9,5 @@ x265 Documentation threading presets lossless + svthevc releasenotes
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/reST/svthevc.rst Thu Feb 14 11:06:36 2019 +0530 @@ -0,0 +1,199 @@ +SVT-HEVC +-------- + +.. _SvtHevc: + +x265 has support for open source HEVC encoder `SVT-HEVC <https://github.com/intel/SVT-HEVC>`_ +and can generate SVT-HEVC compliant bitstreams. SVT-HEVC encoder can be enabled at run time +using :option:`--svt`. Since SVT-HEVC params/CLI are not exposed outside, it has to be +configured only via x265 CLI options. The API's of SVT-HEVC are accessed through x265's API +so even library users of x265 can avail this feature, under the condition that x265_param_parse() +API should be used for all param assignment. Params assigned outside of x265_param_parse() API +wont't be mapped to SVT-HEVC. This document describes the steps needed to compile x265 +with SVT-HEVC and CLI options mapping between x265 and SVT-HEVC. + +Build Steps +=========== +This section describes the build steps to be followed to link SVT-HEVC with x265. + +**SVT-HEVC** + +1. Clone `SVT-HEVC <https://github.com/intel/SVT-HEVC>`_ (say at path "/home/app/") and build it (follow the build steps in its README file) +2. Once build is successful, binaries can be found inside the *Bin* folder at its root directory ("/home/app/SVT-HEVC/Bin/Release/") + +**x265** + +1. Set environmental variables SVT_HEVC_INCLUDE_DIR and SVT_HEVC_LIBRARY_DIR to help x265 locate SVT-HEVC. For example: + * export SVT_HEVC_INCLUDE_DIR = /home/app/SVT-HEVC/Source/API/ + * export SVT_HEVC_LIBRARY_DIR = /home/app/SVT-HEVC/Bin/Release/ +2. Enable the cmake option ENABLE_SVT_HEVC and continue the normal build process + +CLI options Mapping +=================== +Once x265 is compiled with SVT-HEVC, SVT-HEVC encoder can be invoked at run time using +:option:`--svt`. :option:`--svt` can be added anywhere in the command line, x265 application will automatically +parse it first and maps all other x265 CLI's present in the command line to SVT-HEVC encoder options +internally and configures the same. Below table shows the actual mapping of x265 CLI options to +SVT-HEVC encoder options (Name as shown in SVT-HEVC's sample configuration file) + ++-------------------------------------------+------------------------------+------------------------------+ +| x265 CLI option | SVT-HEVC Encoder Option | Range | ++===========================================+==============================+==============================+ +| :option:`--input` | InputFile | Any String | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--output` | StreamFile | Any String | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--input-depth` | EncoderBitDepth | [8, 10] | ++-------------------------------------------+------------------------------+------------------------------+ +| | SourceWidth | [64 - 8192] | +| :option:`--input-res` +------------------------------+------------------------------+ +| | SourceHeight | [64 - 8192] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--frames` | FrameToBeEncoded | Any Positive Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| | FrameRateNumerator | Any Positive Integer | +| :option:`--fps` +------------------------------+------------------------------+ +| | FrameRateDenominator | Any Positive Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--profile` | Profile | [main, main10] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--level-idc` | Level | [1, 2, 2.1, 3, 3.1, 4, 4.1, | +| | | 5, 5.1, 5.2, 6, 6.1, 6.2] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--high-tier` | Tier | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--qpmin` | MinQpAllowed | [0 - 50] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--qpmax` | MaxQpAllowed | [0 - 51] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--rc-lookahead` | LookAheadDistance | [0 - 250] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--scenecut` | SceneChangeDetection | Any Positive Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--open-gop` | IntraRefreshType | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--deblock` | LoopFilterDisable | Any Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--sao` | SAO | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--keyint` | IntraPeriod | [(-2) - 255] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--constrained-intra` | ConstrainedIntra | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--vui-timing-info` | VideoUsabilityInfo | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--hdr` | HighDynamicRangeInput | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--aud` | AccessUnitDelimeter | | ++-------------------------------------------+------------------------------+------------------------------+ +| | RateControlMode | RateControlMode = 0 | +| :option:`--qp` +------------------------------+------------------------------+ +| | QP | [0 - 51] | ++-------------------------------------------+------------------------------+------------------------------+ +| | RateControlMode | RateControlMode = 1 | +| :option:`--bitrate` +------------------------------+------------------------------+ +| | TargetBitrate | Any Positive Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--interlace` | InterlacedVideo | [0 - 2] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--pools` | TargetSocket, | Maximum NUMA Nodes = 2 | +| | LogicalProcessors | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--master-display` | MasteringDisplayColorVolume | Any String | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--max-cll` | maxCLL, maxFALL | Any Positve Integer | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--dolby-vision-profile` | DolbyVisionProfile | [8.1] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--dolby-vision-rpu` | DolbyVisionRpuFile | Any String | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--nalu-file` | NaluFile | Any String | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--tune` zerolatency | LatencyMode | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-search-width` | SearchAreaWidth | [1 - 256] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-search-height` | SearchAreaHeight | [1 - 256] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-hierarchical-level` | HierarchicalLevels | [0 - 3] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-base-layer-switch-mode` | BaseLayerSwitchMode | [0, 1] | +| | | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-pred-struct` | PredStructure | [0 - 2] | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-hme` | HME, UseDefaultMeHme | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-compressed-ten-bit-format` | CompressedTenBitFormat | | +| | | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-speed-control` | SpeedControlFlag | | ++-------------------------------------------+------------------------------+------------------------------+ +| :option:`--svt-fps-in-vps` | FpsInVps | | ++-------------------------------------------+------------------------------+------------------------------+ + +x265 CLI options which are not present in the above table will have no effect if SVT-HEVC is enabled +and would be ignored silently with a warning. If SVT-HEVC is enabled, accepted input range of x265 CLI +options will change, because it follows SVT-HEVC encoder's specs, which are mentioned in the Range +section in the above table. Options starting with prefix "--svt-" are newly added to +fecilitate access to the features of SVT-HEVC which couldn't be mapped to the existing x265 CLI's. +So these options will have effect only if SVT-HEVC is enabled and would be ignored with default x265 encode. + +Preset & Tune Options Mapping +============================= +x265 has 10 presets from ultrafast to placebo whereas SVT-HEVC has 13 presets. Use :option:`--svt-preset-tuner` +with Placebo preset to access the additional 3 presets of SVT-HEVC. Note that :option:`--svt-preset-tuner` should be +used only if SVT-HEVC is enabled and only with Placebo preset, would be ignored otherwise. +Below table shows the actual mapping of presets, + ++----------------------------------------+------------------------------+ +| x265 Preset | SVT-HEVC Preset | ++========================================+==============================+ +| Ultrafast | 12 | ++----------------------------------------+------------------------------+ +| Superfast | 11 | ++----------------------------------------+------------------------------+ +| Veryfast | 10 | ++----------------------------------------+------------------------------+ +| Faster | 9 | ++----------------------------------------+------------------------------+ +| Fast | 8 | ++----------------------------------------+------------------------------+ +| Medium | 7 | ++----------------------------------------+------------------------------+ +| Slow | 6 | ++----------------------------------------+------------------------------+ +| Slower | 5 | ++----------------------------------------+------------------------------+ +| Veryslow | 4 | ++----------------------------------------+------------------------------+ +| Placebo | 3 | ++----------------------------------------+------------------------------+ +| Placebo :option:`--svt-preset-tuner` 0 | 0 | ++----------------------------------------+------------------------------+ +| Placebo :option:`--svt-preset-tuner` 1 | 1 | ++----------------------------------------+------------------------------+ +| Placebo :option:`--svt-preset-tuner` 2 | 2 | ++----------------------------------------+------------------------------+ + +x265 has 5 tune modes (psnr, ssim, grain, zero-latency, animation) whereas SVT-HEVC +has only 2 tune modes (0 - Subjective Quality Mode, 1 - Objective Quality Mode). Below +table shows the mapping of tune modes, + ++-----------------------+---------------------------+ +| x265 Tune Modes | SVT-HEVC Tune Modes | ++=======================+===========================+ +| psnr | 1 | ++-----------------------+---------------------------+ +| ssim | 1 | ++-----------------------+---------------------------+ +| grain | 0 | ++-----------------------+---------------------------+ +| fastdecode | 0 | ++-----------------------+---------------------------+ +| zerolatency | 0 | ++-----------------------+---------------------------+ +| animation | 0 | ++-----------------------+---------------------------+ + +Note that :option:`--tune` animation is also mapped to "LatencyMode" of SVT-HEVC.
--- a/source/CMakeLists.txt Fri Feb 08 16:02:53 2019 +0530 +++ b/source/CMakeLists.txt Thu Feb 14 11:06:36 2019 +0530 @@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CP option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF) mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD) # X265_BUILD must be incremented each time the public API is changed -set(X265_BUILD 169) +set(X265_BUILD 170) configure_file("${PROJECT_SOURCE_DIR}/x265.def.in" "${PROJECT_BINARY_DIR}/x265.def") configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in" @@ -392,6 +392,16 @@ if (ENABLE_HDR10_PLUS) add_subdirectory(dynamicHDR10) add_definitions(-DENABLE_HDR10_PLUS) endif(ENABLE_HDR10_PLUS) + +option(ENABLE_SVT_HEVC "Enable SVT HEVC Encoder" OFF) +if(ENABLE_SVT_HEVC) + find_package(svthevc) + if(SVTHEVC_FOUND) + add_definitions(-DSVT_HEVC) + include_directories(${SVT_HEVC_INCLUDE_DIR}) + endif(SVTHEVC_FOUND) +endif(ENABLE_SVT_HEVC) + # this option can only be used when linking multiple libx265 libraries # together, and some alternate API access method is implemented. option(EXPORT_C_API "Implement public C programming interface" ON) @@ -547,6 +557,9 @@ endif() if(ENABLE_LIBVMAF) target_link_libraries(x265-static ${VMAF}) endif() +if(SVTHEVC_FOUND) + target_link_libraries(x265-static ${SVT_HEVC_LIBRARY}) +endif() install(TARGETS x265-static LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) @@ -556,6 +569,14 @@ if(ENABLE_HDR10_PLUS) LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) endif() + +if(SVTHEVC_FOUND) + install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION include) + install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION include) + install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbTime.h" DESTINATION include) + install(FILES "${SVT_HEVC_LIBRARY}" DESTINATION ${BIN_INSTALL_DIR}) +endif() + install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION include) if((WIN32 AND ENABLE_CLI) OR (WIN32 AND ENABLE_SHARED)) if(MSVC_IDE) @@ -607,7 +628,9 @@ if(ENABLE_SHARED) if(EXTRA_LIB) target_link_libraries(x265-shared ${EXTRA_LIB}) endif() - target_link_libraries(x265-shared ${PLATFORM_LIBS}) + if(SVTHEVC_FOUND) + target_link_libraries(x265-shared ${PLATFORM_LIBS} ${SVT_HEVC_LIBRARY}) + endif(SVTHEVC_FOUND) if(MSVC) set_target_properties(x265-shared PROPERTIES OUTPUT_NAME libx265) else()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/cmake/Findsvthevc.cmake Thu Feb 14 11:06:36 2019 +0530 @@ -0,0 +1,60 @@ +# Module for locating SVT-HEVC Library +# +# SVT_HEVC_INCLUDE_DIR +# Points to the SVT-HEVC include directory. +# +# SVT_HEVC_LIBRARY +# Points to the SVT-HEVC library +# Copyright (c) 2013-2018 MulticoreWare, Inc + +include(FindPackageHandleStandardArgs) + +if(UNIX) +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so") +else() +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") +endif() + +set(SVT_VERSION_MAJOR_REQUIRED 1) +set(SVT_VERSION_MINOR_REQUIRED 3) +set(SVT_VERSION_PATCHLEVEL_REQUIRED 0) + +find_path(SVT_HEVC_INCLUDE_DIR + NAMES EbApi.h EbErrorCodes.h EbTime.h + HINTS $ENV{SVT_HEVC_INCLUDE_DIR} + PATHS ENV + DOC "SVT-HEVC include directory") + +if(SVT_HEVC_INCLUDE_DIR) +file(READ "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" version) + +string(REGEX MATCH "SVT_VERSION_MAJOR ([0-9]*)" _ ${version}) +set(SVT_VERSION_MAJOR ${CMAKE_MATCH_1}) + +string(REGEX MATCH "SVT_VERSION_MINOR ([0-9]*)" _ ${version}) +set(SVT_VERSION_MINOR ${CMAKE_MATCH_1}) + +string(REGEX MATCH "SVT_VERSION_PATCHLEVEL ([0-9]*)" _ ${version}) +set(SVT_VERSION_PATCHLEVEL ${CMAKE_MATCH_1}) + +if(NOT ${SVT_VERSION_MAJOR} EQUAL "1" OR NOT ${SVT_VERSION_MINOR} EQUAL "3" OR NOT ${SVT_VERSION_PATCHLEVEL} EQUAL "0") + message (SEND_ERROR "-- Found SVT-HEVC Lib Version: ${SVT_VERSION_MAJOR}.${SVT_VERSION_MINOR}.${SVT_VERSION_PATCHLEVEL} which doesn't match the required version: ${SVT_VERSION_MAJOR_REQUIRED}.${SVT_VERSION_MINOR_REQUIRED}.${SVT_VERSION_PATCHLEVEL_REQUIRED}; Aborting configure ") +else() + message(STATUS "-- Found SVT-HEVC Lib Version: ${SVT_VERSION_MAJOR}.${SVT_VERSION_MINOR}.${SVT_VERSION_PATCHLEVEL}") +endif() + +endif() + +find_library(SVT_HEVC_LIBRARY +if(UNIX) + NAMES SvtHevcEnc +else() + NAMES SvtHevcEnc +endif() + HINTS $ENV{SVT_HEVC_LIBRARY_DIR} + PATHS ENV + DOC "SVT-HEVC library") + + +mark_as_advanced(SVT_HEVC_LIBRARY SVT_HEVC_INCLUDE_DIR SVT_HEVC_LIBRARY_DIR) +find_package_handle_standard_args(SVTHEVC REQUIRED_VARS SVT_HEVC_LIBRARY SVT_HEVC_INCLUDE_DIR)
--- a/source/common/param.cpp Fri Feb 08 16:02:53 2019 +0530 +++ b/source/common/param.cpp Thu Feb 14 11:06:36 2019 +0530 @@ -28,6 +28,7 @@ #include "param.h" #include "cpu.h" #include "x265.h" +#include "svt.h" #if _MSC_VER #pragma warning(disable: 4996) // POSIX functions are just fine, thanks @@ -92,16 +93,27 @@ namespace X265_NS { x265_param *x265_param_alloc() { - return (x265_param*)x265_malloc(sizeof(x265_param)); + x265_param* param = (x265_param*)x265_malloc(sizeof(x265_param)); +#ifdef SVT_HEVC + param->svtHevcParam = (EB_H265_ENC_CONFIGURATION*)x265_malloc(sizeof(EB_H265_ENC_CONFIGURATION)); +#endif + return param; } void x265_param_free(x265_param* p) { +#ifdef SVT_HEVC + x265_free(p->svtHevcParam); +#endif x265_free(p); } void x265_param_default(x265_param* param) { +#ifdef SVT_HEVC + EB_H265_ENC_CONFIGURATION* svtParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; +#endif + memset(param, 0, sizeof(x265_param)); /* Applying default values to all elements in the param structure */ @@ -317,6 +329,15 @@ void x265_param_default(x265_param* para /* SEI messages */ param->preferredTransferCharacteristics = -1; param->pictureStructure = -1; + + /* SVT Hevc Encoder specific params */ + param->bEnableSvtHevc = 0; + param->svtHevcParam = NULL; + +#ifdef SVT_HEVC + param->svtHevcParam = svtParam; + svt_param_default(param); +#endif } int x265_param_default_preset(x265_param* param, const char* preset, const char* tune) @@ -553,6 +574,11 @@ int x265_param_default_preset(x265_param return -1; } +#ifdef SVT_HEVC + if (svt_set_preset_tune(param, preset, tune)) + return -1; +#endif + return 0; } @@ -707,10 +733,12 @@ int x265_param_parse(x265_param* p, cons bool bValueWasNull = !value; bool bExtraParams = false; char nameBuf[64]; + static int count; if (!name) return X265_PARAM_BAD_NAME; + count++; // skip -- prefix if provided if (name[0] == '-' && name[1] == '-') name += 2; @@ -746,6 +774,19 @@ int x265_param_parse(x265_param* p, cons #endif #define OPT(STR) else if (!strcmp(name, STR)) #define OPT2(STR1, STR2) else if (!strcmp(name, STR1) || !strcmp(name, STR2)) + +#ifdef SVT_HEVC + if (p->bEnableSvtHevc) + { + if(svt_param_parse(p, name, value)) + { + x265_log(p, X265_LOG_ERROR, "Error while parsing params \n"); + bError = true; + } + return bError ? X265_PARAM_BAD_VALUE : 0; + } +#endif + if (0) ; OPT("asm") { @@ -1197,6 +1238,28 @@ int x265_param_parse(x265_param* p, cons OPT("refine-ctu-distortion") p->ctuDistortionRefine = atoi(value); OPT("hevc-aq") p->rc.hevcAq = atobool(value); OPT("qp-adaptation-range") p->rc.qpAdaptationRange = atof(value); +#ifdef SVT_HEVC + OPT("svt") + { + p->bEnableSvtHevc = atobool(value); + if (count > 1 && p->bEnableSvtHevc) + { + x265_log(NULL, X265_LOG_ERROR, "Enable SVT should be the first call to x265_parse_parse \n"); + bError = true; + } + } + OPT("svt-hme") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-search-width") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-search-height") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-compressed-ten-bit-format") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-speed-control") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("input-depth") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-preset-tuner") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-hierarchical-level") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-base-layer-switch-mode") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-pred-struct") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); + OPT("svt-fps-in-vps") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); +#endif else return X265_PARAM_BAD_NAME; } @@ -1974,6 +2037,7 @@ char *x265_param2string(x265_param* p, i BOOL(p->bDynamicRefine, "dynamic-refine"); BOOL(p->bSingleSeiNal, "single-sei"); BOOL(p->rc.hevcAq, "hevc-aq"); + BOOL(p->bEnableSvtHevc, "svt"); s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange); #undef BOOL return buf; @@ -2049,4 +2113,568 @@ bool parseLambdaFile(x265_param* param) return false; } +void x265_copy_params(x265_param* dst, x265_param* src) +{ + dst->cpuid = src->cpuid; + dst->frameNumThreads = src->frameNumThreads; + if (src->numaPools) dst->numaPools = strdup(src->numaPools); + else dst->numaPools = NULL; + + dst->bEnableWavefront = src->bEnableWavefront; + dst->bDistributeModeAnalysis = src->bDistributeModeAnalysis; + dst->bDistributeMotionEstimation = src->bDistributeMotionEstimation; + dst->bLogCuStats = src->bLogCuStats; + dst->bEnablePsnr = src->bEnablePsnr; + dst->bEnableSsim = src->bEnableSsim; + dst->logLevel = src->logLevel; + dst->csvLogLevel = src->csvLogLevel; + if (src->csvfn) dst->csvfn = strdup(src->csvfn); + else dst->csvfn = NULL; + dst->internalBitDepth = src->internalBitDepth; + dst->internalCsp = src->internalCsp; + dst->fpsNum = src->fpsNum; + dst->fpsDenom = src->fpsDenom; + dst->sourceHeight = src->sourceHeight; + dst->sourceWidth = src->sourceWidth; + dst->interlaceMode = src->interlaceMode; + dst->totalFrames = src->totalFrames; + dst->levelIdc = src->levelIdc; + dst->bHighTier = src->bHighTier; + dst->uhdBluray = src->uhdBluray; + dst->maxNumReferences = src->maxNumReferences; + dst->bAllowNonConformance = src->bAllowNonConformance; + dst->bRepeatHeaders = src->bRepeatHeaders; + dst->bAnnexB = src->bAnnexB; + dst->bEnableAccessUnitDelimiters = src->bEnableAccessUnitDelimiters; + dst->bEmitInfoSEI = src->bEmitInfoSEI; + dst->decodedPictureHashSEI = src->decodedPictureHashSEI; + dst->bEnableTemporalSubLayers = src->bEnableTemporalSubLayers; + dst->bOpenGOP = src->bOpenGOP; + dst->keyframeMax = src->keyframeMax; + dst->keyframeMin = src->keyframeMin; + dst->bframes = src->bframes; + dst->bFrameAdaptive = src->bFrameAdaptive; + dst->bFrameBias = src->bFrameBias; + dst->bBPyramid = src->bBPyramid; + dst->lookaheadDepth = src->lookaheadDepth; + dst->lookaheadSlices = src->lookaheadSlices; + dst->lookaheadThreads = src->lookaheadThreads; + dst->scenecutThreshold = src->scenecutThreshold; + dst->bIntraRefresh = src->bIntraRefresh; + dst->maxCUSize = src->maxCUSize; + dst->minCUSize = src->minCUSize; + dst->bEnableRectInter = src->bEnableRectInter; + dst->bEnableAMP = src->bEnableAMP; + dst->maxTUSize = src->maxTUSize; + dst->tuQTMaxInterDepth = src->tuQTMaxInterDepth; + dst->tuQTMaxIntraDepth = src->tuQTMaxIntraDepth; + dst->limitTU = src->limitTU; + dst->rdoqLevel = src->rdoqLevel; + dst->bEnableSignHiding = src->bEnableSignHiding; + dst->bEnableTransformSkip = src->bEnableTransformSkip; + dst->noiseReductionInter = src->noiseReductionInter; + dst->noiseReductionIntra = src->noiseReductionIntra; + if (src->scalingLists) dst->scalingLists = strdup(src->scalingLists); + else dst->scalingLists = NULL; + dst->bEnableStrongIntraSmoothing = src->bEnableStrongIntraSmoothing; + dst->bEnableConstrainedIntra = src->bEnableConstrainedIntra; + dst->maxNumMergeCand = src->maxNumMergeCand; + dst->limitReferences = src->limitReferences; + dst->limitModes = src->limitModes; + dst->searchMethod = src->searchMethod; + dst->subpelRefine = src->subpelRefine; + dst->searchRange = src->searchRange; + dst->bEnableTemporalMvp = src->bEnableTemporalMvp; + dst->bEnableWeightedBiPred = src->bEnableWeightedBiPred; + dst->bEnableWeightedPred = src->bEnableWeightedPred; + dst->bSourceReferenceEstimation = src->bSourceReferenceEstimation; + dst->bEnableLoopFilter = src->bEnableLoopFilter; + dst->deblockingFilterBetaOffset = src->deblockingFilterBetaOffset; + dst->deblockingFilterTCOffset = src->deblockingFilterTCOffset; + dst->bEnableSAO = src->bEnableSAO; + dst->bSaoNonDeblocked = src->bSaoNonDeblocked; + dst->rdLevel = src->rdLevel; + dst->bEnableEarlySkip = src->bEnableEarlySkip; + dst->bEnableRecursionSkip = src->bEnableRecursionSkip; + dst->bEnableFastIntra = src->bEnableFastIntra; + dst->bEnableTSkipFast = src->bEnableTSkipFast; + dst->bCULossless = src->bCULossless; + dst->bIntraInBFrames = src->bIntraInBFrames; + dst->rdPenalty = src->rdPenalty; + dst->psyRd = src->psyRd; + dst->psyRdoq = src->psyRdoq; + dst->bEnableRdRefine = src->bEnableRdRefine; + dst->analysisReuseMode = src->analysisReuseMode; + if (src->analysisReuseFileName) dst->analysisReuseFileName=strdup(src->analysisReuseFileName); + else dst->analysisReuseFileName = NULL; + dst->bLossless = src->bLossless; + dst->cbQpOffset = src->cbQpOffset; + dst->crQpOffset = src->crQpOffset; + dst->preferredTransferCharacteristics = src->preferredTransferCharacteristics; + dst->pictureStructure = src->pictureStructure; + + dst->rc.rateControlMode = src->rc.rateControlMode; + dst->rc.qp = src->rc.qp; + dst->rc.bitrate = src->rc.bitrate; + dst->rc.qCompress = src->rc.qCompress; + dst->rc.ipFactor = src->rc.ipFactor; + dst->rc.pbFactor = src->rc.pbFactor; + dst->rc.rfConstant = src->rc.rfConstant; + dst->rc.qpStep = src->rc.qpStep; + dst->rc.aqMode = src->rc.aqMode; + dst->rc.aqStrength = src->rc.aqStrength; + dst->rc.vbvBufferSize = src->rc.vbvBufferSize; + dst->rc.vbvMaxBitrate = src->rc.vbvMaxBitrate; + + dst->rc.vbvBufferInit = src->rc.vbvBufferInit; + dst->rc.cuTree = src->rc.cuTree; + dst->rc.rfConstantMax = src->rc.rfConstantMax; + dst->rc.rfConstantMin = src->rc.rfConstantMin; + dst->rc.bStatWrite = src->rc.bStatWrite; + dst->rc.bStatRead = src->rc.bStatRead; + if (src->rc.statFileName) dst->rc.statFileName=strdup(src->rc.statFileName); + else dst->rc.statFileName = NULL; + dst->rc.qblur = src->rc.qblur; + dst->rc.complexityBlur = src->rc.complexityBlur; + dst->rc.bEnableSlowFirstPass = src->rc.bEnableSlowFirstPass; + dst->rc.zoneCount = src->rc.zoneCount; + dst->rc.zonefileCount = src->rc.zonefileCount; + + if (src->rc.zones) + { + dst->rc.zones->startFrame = src->rc.zones->startFrame; + dst->rc.zones->endFrame = src->rc.zones->endFrame; + dst->rc.zones->bForceQp = src->rc.zones->bForceQp; + dst->rc.zones->qp = src->rc.zones->qp; + dst->rc.zones->bitrateFactor = src->rc.zones->bitrateFactor; + } + else + dst->rc.zones = NULL; + + if (src->rc.lambdaFileName) dst->rc.lambdaFileName = strdup(src->rc.lambdaFileName); + else dst->rc.lambdaFileName = NULL; + dst->rc.bStrictCbr = src->rc.bStrictCbr; + dst->rc.qgSize = src->rc.qgSize; + dst->rc.bEnableGrain = src->rc.bEnableGrain; + dst->rc.qpMax = src->rc.qpMax; + dst->rc.qpMin = src->rc.qpMin; + dst->rc.bEnableConstVbv = src->rc.bEnableConstVbv; + dst->rc.hevcAq = src->rc.hevcAq; + dst->rc.qpAdaptationRange = src->rc.qpAdaptationRange; + + dst->vui.aspectRatioIdc = src->vui.aspectRatioIdc; + dst->vui.sarWidth = src->vui.sarWidth; + dst->vui.sarHeight = src->vui.sarHeight; + dst->vui.bEnableOverscanAppropriateFlag = src->vui.bEnableOverscanAppropriateFlag; + dst->vui.bEnableOverscanInfoPresentFlag = src->vui.bEnableOverscanInfoPresentFlag; + dst->vui.bEnableVideoSignalTypePresentFlag = src->vui.bEnableVideoSignalTypePresentFlag; + dst->vui.videoFormat = src->vui.videoFormat; + dst->vui.bEnableVideoFullRangeFlag = src->vui.bEnableVideoFullRangeFlag; + dst->vui.bEnableColorDescriptionPresentFlag = src->vui.bEnableColorDescriptionPresentFlag; + dst->vui.colorPrimaries = src->vui.colorPrimaries; + dst->vui.transferCharacteristics = src->vui.transferCharacteristics; + dst->vui.matrixCoeffs = src->vui.matrixCoeffs; + dst->vui.bEnableChromaLocInfoPresentFlag = src->vui.bEnableChromaLocInfoPresentFlag; + dst->vui.chromaSampleLocTypeTopField = src->vui.chromaSampleLocTypeTopField; + dst->vui.chromaSampleLocTypeBottomField = src->vui.chromaSampleLocTypeBottomField; + dst->vui.bEnableDefaultDisplayWindowFlag = src->vui.bEnableDefaultDisplayWindowFlag; + dst->vui.defDispWinBottomOffset = src->vui.defDispWinBottomOffset; + dst->vui.defDispWinLeftOffset = src->vui.defDispWinLeftOffset; + dst->vui.defDispWinRightOffset = src->vui.defDispWinRightOffset; + dst->vui.defDispWinTopOffset = src->vui.defDispWinTopOffset; + + if (src->masteringDisplayColorVolume) dst->masteringDisplayColorVolume=strdup( src->masteringDisplayColorVolume); + else dst->masteringDisplayColorVolume = NULL; + dst->maxLuma = src->maxLuma; + dst->minLuma = src->minLuma; + dst->maxCLL = src->maxCLL; + dst->maxFALL = src->maxFALL; + dst->log2MaxPocLsb = src->log2MaxPocLsb; + dst->bEmitVUIHRDInfo = src->bEmitVUIHRDInfo; + dst->bEmitVUITimingInfo = src->bEmitVUITimingInfo; + dst->maxSlices = src->maxSlices; + dst->bOptQpPPS = src->bOptQpPPS; + dst->bOptRefListLengthPPS = src->bOptRefListLengthPPS; + dst->bMultiPassOptRPS = src->bMultiPassOptRPS; + dst->scenecutBias = src->scenecutBias; + dst->gopLookahead = src->lookaheadDepth; + dst->bOptCUDeltaQP = src->bOptCUDeltaQP; + dst->analysisMultiPassDistortion = src->analysisMultiPassDistortion; + dst->analysisMultiPassRefine = src->analysisMultiPassRefine; + dst->bAQMotion = src->bAQMotion; + dst->bSsimRd = src->bSsimRd; + dst->dynamicRd = src->dynamicRd; + dst->bEmitHDRSEI = src->bEmitHDRSEI; + dst->bEmitHRDSEI = src->bEmitHRDSEI; + dst->bHDROpt = src->bHDROpt; + dst->analysisReuseLevel = src->analysisReuseLevel; + dst->bLimitSAO = src->bLimitSAO; + if (src->toneMapFile) dst->toneMapFile = strdup(src->toneMapFile); + else dst->toneMapFile = NULL; + dst->bDhdr10opt = src->bDhdr10opt; + dst->bCTUInfo = src->bCTUInfo; + dst->bUseRcStats = src->bUseRcStats; + dst->interRefine = src->interRefine; + dst->intraRefine = src->intraRefine; + dst->mvRefine = src->mvRefine; + dst->maxLog2CUSize = src->maxLog2CUSize; + dst->maxCUDepth = src->maxCUDepth; + dst->unitSizeDepth = src->unitSizeDepth; + dst->num4x4Partitions = src->num4x4Partitions; + + dst->csvfpt = src->csvfpt; + dst->bEnableSplitRdSkip = src->bEnableSplitRdSkip; + dst->bUseAnalysisFile = src->bUseAnalysisFile; + dst->forceFlush = src->forceFlush; + dst->bDisableLookahead = src->bDisableLookahead; + dst->bLowPassDct = src->bLowPassDct; + dst->vbvBufferEnd = src->vbvBufferEnd; + dst->vbvEndFrameAdjust = src->vbvEndFrameAdjust; + + dst->bCopyPicToFrame = src->bCopyPicToFrame; + if (src->analysisSave) dst->analysisSave=strdup(src->analysisSave); + else dst->analysisSave = NULL; + if (src->analysisLoad) dst->analysisLoad=strdup(src->analysisLoad); + else dst->analysisLoad = NULL; + dst->gopLookahead = src->gopLookahead; + dst->radl = src->radl; + dst->maxAUSizeFactor = src->maxAUSizeFactor; + dst->bEmitIDRRecoverySEI = src->bEmitIDRRecoverySEI; + dst->bDynamicRefine = src->bDynamicRefine; + dst->bSingleSeiNal = src->bSingleSeiNal; + dst->chunkStart = src->chunkStart; + dst->chunkEnd = src->chunkEnd; + if (src->naluFile) dst->naluFile=strdup(src->naluFile); + else dst->naluFile = NULL; + dst->scaleFactor = src->scaleFactor; + dst->ctuDistortionRefine = src->ctuDistortionRefine; + dst->bEnableHRDConcatFlag = src->bEnableHRDConcatFlag; + dst->dolbyProfile = src->dolbyProfile; + dst->bEnableSvtHevc = src->bEnableSvtHevc; + +#ifdef SVT_HEVC + memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION)); +#endif } + +#ifdef SVT_HEVC + +void svt_param_default(x265_param* param) +{ + EB_H265_ENC_CONFIGURATION* svtHevcParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + + // Channel info + svtHevcParam->channelId = 0; + svtHevcParam->activeChannelCount = 0; + + // GOP Structure + svtHevcParam->intraPeriodLength = -2; + svtHevcParam->intraRefreshType = 1; + svtHevcParam->predStructure = 2; + svtHevcParam->baseLayerSwitchMode = 0; + svtHevcParam->hierarchicalLevels = 3; + svtHevcParam->sourceWidth = 0; + svtHevcParam->sourceHeight = 0; + svtHevcParam->latencyMode = 0; + + //Preset & Tune + svtHevcParam->encMode = 9; + svtHevcParam->tune = 0; + + // Interlaced Video + svtHevcParam->interlacedVideo = 0; + + // Quantization + svtHevcParam->qp = 32; + svtHevcParam->useQpFile = 0; + + // Deblock Filter + svtHevcParam->disableDlfFlag = 0; + + // SAO + svtHevcParam->enableSaoFlag = 1; + + // ME Tools + svtHevcParam->useDefaultMeHme = 1; + svtHevcParam->enableHmeFlag = 1; + + // ME Parameters + svtHevcParam->searchAreaWidth = 16; + svtHevcParam->searchAreaHeight = 7; + + // MD Parameters + svtHevcParam->constrainedIntra = 0; + + // Rate Control + svtHevcParam->frameRate = 60; + svtHevcParam->frameRateNumerator = 0; + svtHevcParam->frameRateDenominator = 0; + svtHevcParam->encoderBitDepth = 8; + svtHevcParam->compressedTenBitFormat = 0; + svtHevcParam->rateControlMode = 0; + svtHevcParam->sceneChangeDetection = 1; + svtHevcParam->lookAheadDistance = (uint32_t)~0; + svtHevcParam->framesToBeEncoded = 0; + svtHevcParam->targetBitRate = 7000000; + svtHevcParam->maxQpAllowed = 48; + svtHevcParam->minQpAllowed = 10; + svtHevcParam->bitRateReduction = 1; + + // Thresholds + svtHevcParam->improveSharpness = 1; + svtHevcParam->videoUsabilityInfo = 0; + svtHevcParam->highDynamicRangeInput = 0; + svtHevcParam->accessUnitDelimiter = 0; + svtHevcParam->bufferingPeriodSEI = 0; + svtHevcParam->pictureTimingSEI = 0; + svtHevcParam->registeredUserDataSeiFlag = 0; + svtHevcParam->unregisteredUserDataSeiFlag = 0; + svtHevcParam->recoveryPointSeiFlag = 0; + svtHevcParam->enableTemporalId = 1; + svtHevcParam->profile = 2; + svtHevcParam->tier = 0; + svtHevcParam->level = 0; + + svtHevcParam->injectorFrameRate = 60 << 16; + svtHevcParam->speedControlFlag = 0; + + // ASM Type + svtHevcParam->asmType = 1; + + svtHevcParam->codeVpsSpsPps = 1; + svtHevcParam->codeEosNal = 0; + svtHevcParam->reconEnabled = 0; + svtHevcParam->maxCLL = 0; + svtHevcParam->maxFALL = 0; + svtHevcParam->useMasteringDisplayColorVolume = 0; + svtHevcParam->useNaluFile = 0; + svtHevcParam->whitePointX = 0; + svtHevcParam->whitePointY = 0; + svtHevcParam->maxDisplayMasteringLuminance = 0; + svtHevcParam->minDisplayMasteringLuminance = 0; + svtHevcParam->dolbyVisionProfile = 0; + svtHevcParam->targetSocket = -1; + svtHevcParam->logicalProcessors = 0; + svtHevcParam->switchThreadsToRtPriority = 1; + svtHevcParam->fpsInVps = 0; +} + +int svt_set_preset_tune(x265_param* param, const char* preset, const char* tune) +{ + EB_H265_ENC_CONFIGURATION* svtHevcParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + + if (preset) + { + if (!strcmp(preset, "ultrafast")) svtHevcParam->encMode = 12; + else if (!strcmp(preset, "superfast")) svtHevcParam->encMode = 11; + else if (!strcmp(preset, "veryfast")) svtHevcParam->encMode = 10; + else if (!strcmp(preset, "faster")) svtHevcParam->encMode = 9; + else if (!strcmp(preset, "fast")) svtHevcParam->encMode = 8; + else if (!strcmp(preset, "medium")) svtHevcParam->encMode = 7; + else if (!strcmp(preset, "slow")) svtHevcParam->encMode = 6; + else if (!strcmp(preset, "slower")) svtHevcParam->encMode = 5; + else if (!strcmp(preset, "veryslow")) svtHevcParam->encMode = 4; + else if (!strcmp(preset, "placebo")) svtHevcParam->encMode = 3; + else return -1; + } + if (tune) + { + if (!strcmp(tune, "psnr")) svtHevcParam->tune = 1; + else if (!strcmp(tune, "ssim")) svtHevcParam->tune = 1; + else if (!strcmp(tune, "grain")) svtHevcParam->tune = 0; + else if (!strcmp(tune, "animation")) svtHevcParam->tune = 1; + else if (!strcmp(tune, "zero-latency") || !strcmp(tune, "zerolatency")) svtHevcParam->latencyMode = 1; + else return -1; + } + return 0; +} + +int svt_param_parse(x265_param* param, const char* name, const char* value) +{ + bool bError = false; +#define OPT(STR) else if (!strcmp(name, STR)) + + EB_H265_ENC_CONFIGURATION* svtHevcParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + if (0); + OPT("input-res") bError |= sscanf(value, "%dx%d", &svtHevcParam->sourceWidth, &svtHevcParam->sourceHeight) != 2; + OPT("input-depth") svtHevcParam->encoderBitDepth = atoi(value); + OPT("total-frames") svtHevcParam->framesToBeEncoded = atoi(value); + OPT("frames") svtHevcParam->framesToBeEncoded = atoi(value); + OPT("fps") + { + if (sscanf(value, "%u/%u", &svtHevcParam->frameRateNumerator, &svtHevcParam->frameRateDenominator) == 2) + ; + else + { + int fps = atoi(value); + svtHevcParam->frameRateDenominator = 1; + + if (fps < 1000) + svtHevcParam->frameRate = fps << 16; + else + svtHevcParam->frameRate = fps; + } + } + OPT2("level-idc", "level") + { + /* allow "5.1" or "51", both converted to integer 51 */ + /* if level-idc specifies an obviously wrong value in either float or int, + throw error consistently. Stronger level checking will be done in encoder_open() */ + if (atof(value) < 10) + svtHevcParam->level = (int)(10 * atof(value) + .5); + else if (atoi(value) < 100) + svtHevcParam->level = atoi(value); + else + bError = true; + } + OPT2("pools", "numa-pools") + { + char *pools = strdup(value); + char *temp1, *temp2; + int count = 0; + + for (temp1 = strstr(pools, ","); temp1 != NULL; temp1 = strstr(temp2, ",")) + { + temp2 = ++temp1; + count++; + } + + if (count > 1) + x265_log(param, X265_LOG_WARNING, "SVT-HEVC Encoder supports pools option only upto 2 sockets \n"); + else if (count == 1) + { + temp1 = strtok(pools, ","); + temp2 = strtok(NULL, ","); + + if (!strcmp(temp1, "+")) + { + if (!strcmp(temp2, "+")) svtHevcParam->targetSocket = -1; + else if (!strcmp(temp2, "-")) svtHevcParam->targetSocket = 0; + else svtHevcParam->targetSocket = -1; + } + else if (!strcmp(temp1, "-")) + { + if (!strcmp(temp2, "+")) svtHevcParam->targetSocket = 1; + else if (!strcmp(temp2, "-")) x265_log(param, X265_LOG_ERROR, "Shouldn't exclude both sockets for pools option %s \n", pools); + else if (!strcmp(temp2, "*")) svtHevcParam->targetSocket = 1; + else + { + svtHevcParam->targetSocket = 1; + svtHevcParam->logicalProcessors = atoi(temp2); + } + } + else svtHevcParam->targetSocket = -1; + } + else + { + if (!strcmp(temp1, "*")) svtHevcParam->targetSocket = -1; + else + { + svtHevcParam->targetSocket = 0; + svtHevcParam->logicalProcessors = atoi(temp1); + } + } + } + OPT("high-tier") svtHevcParam->tier = x265_atobool(value, bError); + OPT("qpmin") svtHevcParam->minQpAllowed = atoi(value); + OPT("qpmax") svtHevcParam->maxQpAllowed = atoi(value); + OPT("rc-lookahead") svtHevcParam->lookAheadDistance = atoi(value); + OPT("scenecut") + { + svtHevcParam->sceneChangeDetection = x265_atobool(value, bError); + if (bError || svtHevcParam->sceneChangeDetection) + { + bError = false; + svtHevcParam->sceneChangeDetection = 1; + } + } + OPT("open-gop") + { + if (x265_atobool(value, bError)) + svtHevcParam->intraRefreshType = 1; + else + svtHevcParam->intraRefreshType = 2; + } + OPT("deblock") + { + if (strtol(value, NULL, 0)) + svtHevcParam->disableDlfFlag = 0; + else if (x265_atobool(value, bError) == 0 && !bError) + svtHevcParam->disableDlfFlag = 1; + } + OPT("sao") svtHevcParam->enableSaoFlag = (uint8_t)x265_atobool(value, bError); + OPT("keyint") svtHevcParam->intraPeriodLength = atoi(value); + OPT2("constrained-intra", "cip") svtHevcParam->constrainedIntra = (uint8_t)x265_atobool(value, bError); + OPT("vui-timing-info") svtHevcParam->videoUsabilityInfo = x265_atobool(value, bError); + OPT("hdr") svtHevcParam->highDynamicRangeInput = x265_atobool(value, bError); + OPT("aud") svtHevcParam->accessUnitDelimiter = x265_atobool(value, bError); + OPT("qp") + { + svtHevcParam->rateControlMode = 0; + svtHevcParam->qp = atoi(value); + } + OPT("bitrate") + { + svtHevcParam->rateControlMode = 1; + svtHevcParam->targetBitRate = atoi(value); + } + OPT("interlace") + { + svtHevcParam->interlacedVideo = (uint8_t)x265_atobool(value, bError); + if (bError || svtHevcParam->interlacedVideo) + { + bError = false; + svtHevcParam->interlacedVideo = 1; + } + } + OPT("svt-hme") + { + svtHevcParam->enableHmeFlag = (uint8_t)x265_atobool(value, bError); + if (svtHevcParam->enableHmeFlag) svtHevcParam->useDefaultMeHme = 1; + } + OPT("svt-search-width") svtHevcParam->searchAreaWidth = atoi(value); + OPT("svt-search-height") svtHevcParam->searchAreaHeight = atoi(value); + OPT("svt-compressed-ten-bit-format") svtHevcParam->compressedTenBitFormat = x265_atobool(value, bError); + OPT("svt-speed-control") svtHevcParam->speedControlFlag = x265_atobool(value, bError); + OPT("svt-preset-tuner") + { + if (svtHevcParam->encMode == 3) + { + if (!strcmp(value, "0")) svtHevcParam->encMode = 0; + else if (!strcmp(value, "1")) svtHevcParam->encMode = 1; + else if (!strcmp(value, "2")) svtHevcParam->encMode = 2; + else + { + x265_log(param, X265_LOG_ERROR, " Unsupported value=%s for svt-preset-tuner \n", value); + bError = true; + } + } + else + x265_log(param, X265_LOG_WARNING, " svt-preset-tuner should be used only with ultrafast preset; Ignoring it \n"); + } + OPT("svt-hierarchical-level") svtHevcParam->hierarchicalLevels = atoi(value); + OPT("svt-base-layer-switch-mode") svtHevcParam->baseLayerSwitchMode = atoi(value); + OPT("svt-pred-struct") svtHevcParam->predStructure = (uint8_t)atoi(value); + OPT("svt-fps-in-vps") svtHevcParam->fpsInVps = (uint8_t)x265_atobool(value, bError); + OPT("master-display") svtHevcParam->useMasteringDisplayColorVolume = (uint8_t)atoi(value); + OPT("max-cll") bError |= sscanf(value, "%hu,%hu", &svtHevcParam->maxCLL, &svtHevcParam->maxFALL) != 2; + OPT("nalu-file") svtHevcParam->useNaluFile = (uint8_t)atoi(value); + OPT("dolby-vision-profile") + { + if (atof(value) < 10) + svtHevcParam->dolbyVisionProfile = (int)(10 * atof(value) + .5); + else if (atoi(value) < 100) + svtHevcParam->dolbyVisionProfile = atoi(value); + else + bError = true; + } + else + x265_log(param, X265_LOG_INFO, "SVT doesn't support %s param; Disabling it \n", name); + + + return bError ? X265_PARAM_BAD_VALUE : 0; +} + +#endif //ifdef SVT_HEVC + +}
--- a/source/common/param.h Fri Feb 08 16:02:53 2019 +0530 +++ b/source/common/param.h Thu Feb 14 11:06:36 2019 +0530 @@ -37,6 +37,7 @@ int parseCpuName(const char *value, bo void setParamAspectRatio(x265_param *p, int width, int height); void getParamAspectRatio(x265_param *p, int& width, int& height); bool parseLambdaFile(x265_param *param); +void x265_copy_params(x265_param* dst, x265_param* src); /* this table is kept internal to avoid confusion, since log level indices start at -1 */ static const char * const logLevelNames[] = { "none", "error", "warning", "info", "debug", "full", 0 };
--- a/source/encoder/CMakeLists.txt Fri Feb 08 16:02:53 2019 +0530 +++ b/source/encoder/CMakeLists.txt Thu Feb 14 11:06:36 2019 +0530 @@ -43,4 +43,4 @@ add_library(encoder OBJECT ../x265.h reference.cpp reference.h encoder.cpp encoder.h api.cpp - weightPrediction.cpp) + weightPrediction.cpp svt.h)
--- a/source/encoder/api.cpp Fri Feb 08 16:02:53 2019 +0530 +++ b/source/encoder/api.cpp Thu Feb 14 11:06:36 2019 +0530 @@ -30,6 +30,7 @@ #include "level.h" #include "nal.h" #include "bitcost.h" +#include "svt.h" #if ENABLE_LIBVMAF #include "libvmaf.h" @@ -98,16 +99,64 @@ x265_encoder *x265_encoder_open(x265_par if (!param || !latestParam) goto fail; - memcpy(param, p, sizeof(x265_param)); + x265_copy_params(param, p); x265_log(param, X265_LOG_INFO, "HEVC encoder version %s\n", PFX(version_str)); x265_log(param, X265_LOG_INFO, "build info %s\n", PFX(build_info_str)); + encoder = new Encoder; + +#ifdef SVT_HEVC + + if (param->bEnableSvtHevc) + { + EB_ERRORTYPE return_error = EB_ErrorNone; + int ret = 0; + + svt_initialise_app_context(encoder); + ret = svt_initialise_input_buffer(encoder); + if (!ret) + { + x265_log(param, X265_LOG_ERROR, "SVT-HEVC Encoder: Unable to allocate input buffer \n"); + goto fail; + } + + // Create Encoder Handle + return_error = EbInitHandle(&encoder->m_svtAppData->svtEncoderHandle, encoder->m_svtAppData, encoder->m_svtAppData->svtHevcParams); + if (return_error != EB_ErrorNone) + { + x265_log(param, X265_LOG_ERROR, "SVT-HEVC Encoder: Unable to initialise encoder handle \n"); + goto fail; + } + + memcpy(encoder->m_svtAppData->svtHevcParams, param->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION)); + + // Send over all configuration parameters + return_error = EbH265EncSetParameter(encoder->m_svtAppData->svtEncoderHandle, encoder->m_svtAppData->svtHevcParams); + if (return_error != EB_ErrorNone) + { + x265_log(param, X265_LOG_ERROR, "SVT-HEVC Encoder: Error while configuring encoder parameters \n"); + goto fail; + } + + // Init Encoder + return_error = EbInitEncoder(encoder->m_svtAppData->svtEncoderHandle); + if (return_error != EB_ErrorNone) + { + x265_log(param, X265_LOG_ERROR, "SVT-HEVC Encoder: Encoder init failed \n"); + goto fail; + } + + memcpy(param->svtHevcParam, encoder->m_svtAppData->svtHevcParams, sizeof(EB_H265_ENC_CONFIGURATION)); + encoder->m_param = param; + return encoder; + } +#endif + x265_setup_primitives(param); if (x265_check_params(param)) goto fail; - encoder = new Encoder; if (!param->rc.bEnableSlowFirstPass) PARAM_NS::x265_param_apply_fastfirstpass(param); @@ -146,7 +195,7 @@ x265_encoder *x265_encoder_open(x265_par } encoder->m_latestParam = latestParam; - memcpy(latestParam, param, sizeof(x265_param)); + x265_copy_params(latestParam, param); if (encoder->m_aborted) goto fail; @@ -165,6 +214,33 @@ int x265_encoder_headers(x265_encoder *e if (pp_nal && enc) { Encoder *encoder = static_cast<Encoder*>(enc); +#ifdef SVT_HEVC + if (encoder->m_param->bEnableSvtHevc) + { + EB_ERRORTYPE return_error; + EB_BUFFERHEADERTYPE* outputPtr; + return_error = EbH265EncStreamHeader(encoder->m_svtAppData->svtEncoderHandle, &outputPtr); + if (return_error != EB_ErrorNone) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while generating stream headers \n"); + encoder->m_aborted = true; + return -1; + } + + //Copy data from output packet to NAL + encoder->m_nalList.m_nal[0].payload = outputPtr->pBuffer; + encoder->m_nalList.m_nal[0].sizeBytes = outputPtr->nFilledLen; + *pp_nal = &encoder->m_nalList.m_nal[0]; + *pi_nal = 1; + encoder->m_svtAppData->byteCount += outputPtr->nFilledLen; + + // Release the output buffer + EbH265ReleaseOutBuffer(&outputPtr); + + return pp_nal[0]->sizeBytes; + } +#endif + Entropy sbacCoder; Bitstream bs; if (encoder->m_param->rc.bStatRead && encoder->m_param->bMultiPassOptRPS) @@ -194,7 +270,7 @@ void x265_encoder_parameters(x265_encode if (enc && out) { Encoder *encoder = static_cast<Encoder*>(enc); - memcpy(out, encoder->m_param, sizeof(x265_param)); + x265_copy_params(out, encoder->m_param); } } @@ -211,12 +287,12 @@ int x265_encoder_reconfig(x265_encoder* bool isReconfigureRc = encoder->isReconfigureRc(encoder->m_latestParam, param_in); if ((encoder->m_reconfigure && !isReconfigureRc) || (encoder->m_reconfigureRc && isReconfigureRc)) /* Reconfigure in progress */ return 1; - memcpy(&save, encoder->m_latestParam, sizeof(x265_param)); + x265_copy_params(&save, encoder->m_latestParam); int ret = encoder->reconfigureParam(encoder->m_latestParam, param_in); if (ret) { /* reconfigure failed, recover saved param set */ - memcpy(encoder->m_latestParam, &save, sizeof(x265_param)); + x265_copy_params(encoder->m_latestParam, &save); ret = -1; } else @@ -228,7 +304,7 @@ int x265_encoder_reconfig(x265_encoder* { if (encoder->m_scalingList.parseScalingList(encoder->m_latestParam->scalingLists)) { - memcpy(encoder->m_latestParam, &save, sizeof(x265_param)); + x265_copy_params(encoder->m_latestParam, &save); return -1; } encoder->m_scalingList.setupQuantMatrices(encoder->m_param->internalCsp); @@ -236,7 +312,7 @@ int x265_encoder_reconfig(x265_encoder* else { x265_log(encoder->m_param, X265_LOG_ERROR, "Repeat headers is turned OFF, cannot reconfigure scalinglists\n"); - memcpy(encoder->m_latestParam, &save, sizeof(x265_param)); + x265_copy_params(encoder->m_latestParam, &save); return -1; } } @@ -253,7 +329,7 @@ int x265_encoder_reconfig(x265_encoder* x265_log(encoder->m_param, X265_LOG_WARNING, "Profile/Level/Tier has changed from %d/%d/%s to %d/%d/%s.Cannot reconfigure rate-control.\n", saveVPS.ptl.profileIdc, saveVPS.ptl.levelIdc, saveVPS.ptl.tierFlag ? "High" : "Main", encoder->m_vps.ptl.profileIdc, encoder->m_vps.ptl.levelIdc, encoder->m_vps.ptl.tierFlag ? "High" : "Main"); - memcpy(encoder->m_latestParam, &save, sizeof(x265_param)); + x265_copy_params(encoder->m_latestParam, &save); memcpy(&encoder->m_vps.ptl, &saveVPS.ptl, sizeof(saveVPS.ptl)); encoder->m_reconfigureRc = false; } @@ -274,6 +350,167 @@ int x265_encoder_encode(x265_encoder *en Encoder *encoder = static_cast<Encoder*>(enc); int numEncoded; +#ifdef SVT_HEVC + EB_ERRORTYPE return_error; + static unsigned char picSendDone = 0; + numEncoded = 0; + static int codedNal = 0, eofReached = 0; + + if (encoder->m_param->bEnableSvtHevc) + { + if (pic_in) + { + if (pic_in->colorSpace == X265_CSP_I420) // SVT-HEVC supports only yuv420p color space + { + EB_BUFFERHEADERTYPE *inputPtr = encoder->m_svtAppData->inputPictureBuffer; + + if (pic_in->framesize) inputPtr->nFilledLen = (uint32_t)pic_in->framesize; + inputPtr->nFlags = 0; + inputPtr->pts = pic_in->pts; + inputPtr->dts = pic_in->dts; + inputPtr->sliceType = EB_INVALID_PICTURE; + + EB_H265_ENC_INPUT *inputData = (EB_H265_ENC_INPUT*) inputPtr->pBuffer; + inputData->luma = (unsigned char*) pic_in->planes[0]; + inputData->cb = (unsigned char*) pic_in->planes[1]; + inputData->cr = (unsigned char*) pic_in->planes[2]; + + inputData->yStride = encoder->m_param->sourceWidth; + inputData->cbStride = encoder->m_param->sourceWidth >> 1; + inputData->crStride = encoder->m_param->sourceWidth >> 1; + + inputData->lumaExt = NULL; + inputData->cbExt = NULL; + inputData->crExt = NULL; + + if (pic_in->rpu.payloadSize) + { + inputData->dolbyVisionRpu.payload = X265_MALLOC(uint8_t, 1024); + memcpy(inputData->dolbyVisionRpu.payload, pic_in->rpu.payload, pic_in->rpu.payloadSize); + inputData->dolbyVisionRpu.payloadSize = pic_in->rpu.payloadSize; + inputData->dolbyVisionRpu.payloadType = NAL_UNIT_UNSPECIFIED; + } + else + { + inputData->dolbyVisionRpu.payload = NULL; + inputData->dolbyVisionRpu.payloadSize = 0; + } + + // Send the picture to the encoder + return_error = EbH265EncSendPicture(encoder->m_svtAppData->svtEncoderHandle, inputPtr); + + if (return_error != EB_ErrorNone) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while encoding \n"); + numEncoded = -1; + goto fail; + } + } + else + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC Encoder accepts only yuv420p input \n"); + numEncoded = -1; + goto fail; + } + } + else if (!picSendDone) //Encoder flush + { + picSendDone = 1; + EB_BUFFERHEADERTYPE inputPtrLast; + inputPtrLast.nAllocLen = 0; + inputPtrLast.nFilledLen = 0; + inputPtrLast.nTickCount = 0; + inputPtrLast.pAppPrivate = NULL; + inputPtrLast.nFlags = EB_BUFFERFLAG_EOS; + inputPtrLast.pBuffer = NULL; + + return_error = EbH265EncSendPicture(encoder->m_svtAppData->svtEncoderHandle, &inputPtrLast); + if (return_error != EB_ErrorNone) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while encoding \n"); + numEncoded = -1; + goto fail; + } + } + + EB_H265_ENC_CONFIGURATION* svtParam = (EB_H265_ENC_CONFIGURATION*)encoder->m_svtAppData->svtHevcParams; + if (eofReached && svtParam->codeEosNal == 0 && !codedNal) + { + EB_BUFFERHEADERTYPE *outputStreamPtr = 0; + return_error = EbH265EncEosNal(encoder->m_svtAppData->svtEncoderHandle, &outputStreamPtr); + if (return_error == EB_ErrorMax) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while encoding \n"); + numEncoded = -1; + goto fail; + } + if (return_error != EB_NoErrorEmptyQueue) + { + if (outputStreamPtr->pBuffer) + { + //Copy data from output packet to NAL + encoder->m_nalList.m_nal[0].payload = outputStreamPtr->pBuffer; + encoder->m_nalList.m_nal[0].sizeBytes = outputStreamPtr->nFilledLen; + encoder->m_svtAppData->byteCount += outputStreamPtr->nFilledLen; + *pp_nal = &encoder->m_nalList.m_nal[0]; + *pi_nal = 1; + numEncoded = 0; + codedNal = 1; + return numEncoded; + } + + // Release the output buffer + EbH265ReleaseOutBuffer(&outputStreamPtr); + } + } + else if (eofReached) + { + *pi_nal = 0; + return numEncoded; + } + + //Receive Packet + EB_BUFFERHEADERTYPE *outputPtr; + return_error = EbH265GetPacket(encoder->m_svtAppData->svtEncoderHandle, &outputPtr, picSendDone); + if (return_error == EB_ErrorMax) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while encoding \n"); + numEncoded = -1; + goto fail; + } + + if (return_error != EB_NoErrorEmptyQueue) + { + if (outputPtr->pBuffer) + { + //Copy data from output packet to NAL + encoder->m_nalList.m_nal[0].payload = outputPtr->pBuffer; + encoder->m_nalList.m_nal[0].sizeBytes = outputPtr->nFilledLen; + encoder->m_svtAppData->byteCount += outputPtr->nFilledLen; + encoder->m_svtAppData->outFrameCount++; + *pp_nal = &encoder->m_nalList.m_nal[0]; + *pi_nal = 1; + numEncoded = 1; + } + + eofReached = outputPtr->nFlags & EB_BUFFERFLAG_EOS; + + // Release the output buffer + EbH265ReleaseOutBuffer(&outputPtr); + } + else if (pi_nal) + *pi_nal = 0; + + pic_out = NULL; + +fail: + if (numEncoded < 0) + encoder->m_aborted = true; + + return numEncoded; + } +#endif + // While flushing, we cannot return 0 until the entire stream is flushed do { @@ -353,12 +590,59 @@ void x265_encoder_log(x265_encoder* enc, } } +#ifdef SVT_HEVC +static void svt_print_summary(x265_encoder *enc) +{ + Encoder *encoder = static_cast<Encoder*>(enc); + double frameRate = 0, bitrate = 0; + EB_H265_ENC_CONFIGURATION *svtParam = (EB_H265_ENC_CONFIGURATION*)encoder->m_svtAppData->svtHevcParams; + if (svtParam->frameRateNumerator && svtParam->frameRateDenominator && (svtParam->frameRateNumerator != 0 && svtParam->frameRateDenominator != 0)) + { + frameRate = ((double)svtParam->frameRateNumerator) / ((double)svtParam->frameRateDenominator); + if(encoder->m_svtAppData->outFrameCount) + bitrate = ((double)(encoder->m_svtAppData->byteCount << 3) * frameRate / (encoder->m_svtAppData->outFrameCount * 1000)); + + printf("Total Frames\t\tFrame Rate\t\tByte Count\t\tBitrate\n"); + printf("%12d\t\t%4.2f fps\t\t%10.0f\t\t%5.2f kbps\n", (int32_t)encoder->m_svtAppData->outFrameCount, (double)frameRate, (double)encoder->m_svtAppData->byteCount, bitrate); + } +} +#endif + void x265_encoder_close(x265_encoder *enc) { if (enc) { Encoder *encoder = static_cast<Encoder*>(enc); +#ifdef SVT_HEVC + if (encoder->m_param->bEnableSvtHevc) + { + EB_ERRORTYPE return_value; + return_value = EbDeinitEncoder(encoder->m_svtAppData->svtEncoderHandle); + if (return_value != EB_ErrorNone) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while closing the encoder \n"); + } + return_value = EbDeinitHandle(encoder->m_svtAppData->svtEncoderHandle); + if (return_value != EB_ErrorNone) + { + x265_log(encoder->m_param, X265_LOG_ERROR, "SVT HEVC encoder: Error while closing the Handle \n"); + } + + svt_print_summary(enc); + EB_H265_ENC_INPUT *inputData = (EB_H265_ENC_INPUT*)encoder->m_svtAppData->inputPictureBuffer->pBuffer; + if (inputData->dolbyVisionRpu.payload) X265_FREE(inputData->dolbyVisionRpu.payload); + + X265_FREE(inputData); + X265_FREE(encoder->m_svtAppData->inputPictureBuffer); + X265_FREE(encoder->m_svtAppData->svtHevcParams); + encoder->stopJobs(); + encoder->destroy(); + delete encoder; + return; + } +#endif + encoder->stopJobs(); encoder->printSummary(); encoder->destroy(); @@ -1633,4 +1917,44 @@ double x265_calculate_vmaf_framelevelsco return score; } #endif + } /* end namespace or extern "C" */ + +namespace X265_NS { +#ifdef SVT_HEVC + +void svt_initialise_app_context(x265_encoder *enc) +{ + Encoder *encoder = static_cast<Encoder*>(enc); + + //Initialise Application Context + encoder->m_svtAppData = (SvtAppContext*)x265_malloc(sizeof(SvtAppContext)); + encoder->m_svtAppData->svtHevcParams = (EB_H265_ENC_CONFIGURATION*)x265_malloc(sizeof(EB_H265_ENC_CONFIGURATION)); + encoder->m_svtAppData->byteCount = 0; + encoder->m_svtAppData->outFrameCount = 0; +} + +int svt_initialise_input_buffer(x265_encoder *enc) +{ + Encoder *encoder = static_cast<Encoder*>(enc); + + //Initialise Input Buffer + encoder->m_svtAppData->inputPictureBuffer = (EB_BUFFERHEADERTYPE*)x265_malloc(sizeof(EB_BUFFERHEADERTYPE)); + EB_BUFFERHEADERTYPE *inputPtr = encoder->m_svtAppData->inputPictureBuffer; + inputPtr->pBuffer = (unsigned char*)x265_malloc(sizeof(EB_H265_ENC_INPUT)); + + EB_H265_ENC_INPUT *inputData = (EB_H265_ENC_INPUT*)inputPtr->pBuffer; + inputData->dolbyVisionRpu.payload = NULL; + inputData->dolbyVisionRpu.payloadSize = 0; + + + if (!inputPtr->pBuffer) + return 0; + + inputPtr->nSize = sizeof(EB_BUFFERHEADERTYPE); + inputPtr->pAppPrivate = NULL; + return 1; +} +#endif // ifdef SVT_HEVC + +} // end namespace X265_NS \ No newline at end of file
--- a/source/encoder/encoder.cpp Fri Feb 08 16:02:53 2019 +0530 +++ b/source/encoder/encoder.cpp Thu Feb 14 11:06:36 2019 +0530 @@ -124,6 +124,10 @@ Encoder::Encoder() m_cim = NULL; #endif +#if SVT_HEVC + m_svtAppData = NULL; +#endif + m_prevTonemapPayload.payload = NULL; m_startPoint = 0; m_saveCTUSize = 0; @@ -827,6 +831,10 @@ void Encoder::destroy() } if (m_naluFile) fclose(m_naluFile); + +#ifdef SVT_HEVC + X265_FREE(m_svtAppData); +#endif if (m_param) { if (m_param->csvfpt) @@ -1471,7 +1479,7 @@ int Encoder::encode(const x265_picture* if (frameEnc->m_reconfigureRc && m_reconfigureRc) { - memcpy(m_param, m_latestParam, sizeof(x265_param)); + x265_copy_params(m_param, m_latestParam); m_rateControl->reconfigureRC(); m_reconfigureRc = false; } @@ -1483,7 +1491,7 @@ int Encoder::encode(const x265_picture* /* Safe to copy m_latestParam to Encoder::m_param, encoder reconfigure complete */ for (int frameEncId = 0; frameEncId < m_param->frameNumThreads; frameEncId++) m_frameEncoder[frameEncId]->m_reconfigure = false; - memcpy (m_param, m_latestParam, sizeof(x265_param)); + x265_copy_params(m_param, m_latestParam); m_reconfigure = false; }
--- a/source/encoder/encoder.h Fri Feb 08 16:02:53 2019 +0530 +++ b/source/encoder/encoder.h Thu Feb 14 11:06:36 2019 +0530 @@ -31,6 +31,7 @@ #include "x265.h" #include "nal.h" #include "framedata.h" +#include "svt.h" #ifdef ENABLE_HDR10_PLUS #include "dynamicHDR10/hdr10plus.h" #endif @@ -41,6 +42,20 @@ extern const char g_sliceTypeToChar[3]; class Entropy; +#ifdef SVT_HEVC +typedef struct SvtAppContext +{ + EB_COMPONENTTYPE* svtEncoderHandle; + EB_H265_ENC_CONFIGURATION* svtHevcParams; + + // Buffer Pools + EB_BUFFERHEADERTYPE* inputPictureBuffer; + uint64_t byteCount; + uint64_t outFrameCount; + +}SvtAppContext; +#endif + struct EncStats { double m_psnrSumY; @@ -224,6 +239,10 @@ public: int m_numCimInfo; #endif +#ifdef SVT_HEVC + SvtAppContext* m_svtAppData; +#endif + x265_sei_payload m_prevTonemapPayload; /* Collect frame level feature data */
--- a/source/encoder/level.cpp Fri Feb 08 16:02:53 2019 +0530 +++ b/source/encoder/level.cpp Thu Feb 14 11:06:36 2019 +0530 @@ -25,6 +25,7 @@ #include "common.h" #include "slice.h" #include "level.h" +#include "svt.h" namespace X265_NS { typedef struct @@ -435,6 +436,21 @@ int x265_param_apply_profile(x265_param if (!param || !profile) return 0; +#ifdef SVT_HEVC + if (param->bEnableSvtHevc) + { + EB_H265_ENC_CONFIGURATION* svtParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + if (!strcmp(profile, "main")) svtParam->profile = 1; + else if (!strcmp(profile, "main10")) svtParam->profile = 2; + else + { + x265_log(param, X265_LOG_ERROR, "SVT-HEVC encoder: Unsupported profile %s \n", profile); + return -1; + } + return 0; + } +#endif + /* Check if profile bit-depth requirement is exceeded by internal bit depth */ bool bInvalidDepth = false; #if X265_DEPTH > 8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/encoder/svt.h Thu Feb 14 11:06:36 2019 +0530 @@ -0,0 +1,52 @@ +/***************************************************************************** +* Copyright (C) 2013-2018 MulticoreWare, Inc +* +* Authors: Radhakrishnan <radhakrishnan@multicorewareinc.com> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. +* +* This program is also available under a commercial proprietary license. +* For more information, contact us at license @ x265.com. +*****************************************************************************/ + + +#ifndef SVT_H +#define SVT_H + +#ifdef SVT_HEVC + +#include "EbApi.h" +#include "EbErrorCodes.h" +#include "EbTime.h" + +namespace X265_NS { + +#define INPUT_SIZE_576p_TH 0x90000 // 0.58 Million +#define INPUT_SIZE_1080i_TH 0xB71B0 // 0.75 Million +#define INPUT_SIZE_1080p_TH 0x1AB3F0 // 1.75 Million +#define INPUT_SIZE_4K_TH 0x29F630 // 2.75 Million + +#define EB_OUTPUTSTREAMBUFFERSIZE_MACRO(ResolutionSize) ((ResolutionSize) < (INPUT_SIZE_1080i_TH) ? 0x1E8480 : (ResolutionSize) < (INPUT_SIZE_1080p_TH) ? 0x2DC6C0 : (ResolutionSize) < (INPUT_SIZE_4K_TH) ? 0x2DC6C0 : 0x2DC6C0) + +void svt_param_default(x265_param* param); +int svt_set_preset_tune(x265_param* param, const char* preset, const char* tune); +int svt_param_parse(x265_param* param, const char* name, const char* value); +void svt_initialise_app_context(x265_encoder *enc); +int svt_initialise_input_buffer(x265_encoder *enc); +} + +#endif // ifdef SVT_HEVC + +#endif // ifndef SVT_H \ No newline at end of file
--- a/source/x265.cpp Fri Feb 08 16:02:53 2019 +0530 +++ b/source/x265.cpp Thu Feb 14 11:06:36 2019 +0530 @@ -31,6 +31,7 @@ #include "input/input.h" #include "output/output.h" #include "output/reconplay.h" +#include "svt.h" #if HAVE_VLD /* Visual Leak Detector */ @@ -287,6 +288,7 @@ bool CLIOptions::parse(int argc, char ** const char *preset = NULL; const char *tune = NULL; const char *profile = NULL; + int svtEnabled = 0; if (argc <= 1) { @@ -297,7 +299,8 @@ bool CLIOptions::parse(int argc, char ** /* Presets are applied before all other options. */ for (optind = 0;; ) { - int c = getopt_long(argc, argv, short_options, long_options, NULL); + int optionsIndex = -1; + int c = getopt_long(argc, argv, short_options, long_options, &optionsIndex); if (c == -1) break; else if (c == 'p') @@ -310,6 +313,8 @@ bool CLIOptions::parse(int argc, char ** profile = optarg; else if (c == '?') bShowHelp = true; + else if (!c && !strcmp(long_options[optionsIndex].name, "svt")) + svtEnabled = 1; } if (!outputBitDepth && profile) @@ -357,6 +362,9 @@ bool CLIOptions::parse(int argc, char ** showHelp(param); } + //Set enable SVT-HEVC encoder first if found in the command line + if (svtEnabled) api->param_parse(param, "svt", NULL); + for (optind = 0;; ) { int long_options_index = -1; @@ -423,6 +431,7 @@ bool CLIOptions::parse(int argc, char ** OPT("tune") /* handled above */; OPT("output-depth") /* handled above */; OPT("recon-y4m-exec") reconPlayCmd = optarg; + OPT("svt") /* handled above */; OPT("qpfile") { this->qpfile = x265_fopen(optarg, "rb"); @@ -492,6 +501,18 @@ bool CLIOptions::parse(int argc, char ** return true; } +#ifdef SVT_HEVC + if (svtEnabled) + { + EB_H265_ENC_CONFIGURATION* svtParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + param->sourceWidth = svtParam->sourceWidth; + param->sourceHeight = svtParam->sourceHeight; + param->fpsNum = svtParam->frameRateNumerator; + param->fpsDenom = svtParam->frameRateDenominator; + svtParam->encoderBitDepth = inputBitDepth; + } +#endif + InputFileInfo info; info.filename = inputfn; info.depth = inputBitDepth; @@ -536,6 +557,18 @@ bool CLIOptions::parse(int argc, char ** if (this->framesToBeEncoded == 0 && info.frameCount > (int)seek) this->framesToBeEncoded = info.frameCount - seek; param->totalFrames = this->framesToBeEncoded; + +#ifdef SVT_HEVC + if (svtEnabled) + { + EB_H265_ENC_CONFIGURATION* svtParam = (EB_H265_ENC_CONFIGURATION*)param->svtHevcParam; + svtParam->sourceWidth = param->sourceWidth; + svtParam->sourceHeight = param->sourceHeight; + svtParam->frameRateNumerator = param->fpsNum; + svtParam->frameRateDenominator = param->fpsDenom; + svtParam->framesToBeEncoded = param->totalFrames; + } +#endif /* Force CFR until we have support for VFR */ info.timebaseNum = param->fpsDenom; @@ -884,7 +917,7 @@ int main(int argc, char **argv) int ret = 0; - if (!param->bRepeatHeaders) + if (!param->bRepeatHeaders && !param->bEnableSvtHevc) { if (api->encoder_headers(encoder, &p_nal, &nal) < 0) {
--- a/source/x265.h Fri Feb 08 16:02:53 2019 +0530 +++ b/source/x265.h Thu Feb 14 11:06:36 2019 +0530 @@ -1765,6 +1765,12 @@ typedef struct x265_param * 0 - Disabled. 1 - Save/Load ctu distortion to/from the file specified * analysis-save/load. Default 0. */ int ctuDistortionRefine; + + /* Enable SVT HEVC Encoder */ + int bEnableSvtHevc; + + /* SVT-HEVC param structure. For internal use when SVT HEVC encoder is enabled */ + void* svtHevcParam; } x265_param; /* x265_param_alloc: * Allocates an x265_param instance. The returned param structure is not
--- a/source/x265cli.h Fri Feb 08 16:02:53 2019 +0530 +++ b/source/x265cli.h Thu Feb 14 11:06:36 2019 +0530 @@ -314,6 +314,24 @@ static const struct option long_options[ { "hevc-aq", no_argument, NULL, 0 }, { "no-hevc-aq", no_argument, NULL, 0 }, { "qp-adaptation-range", required_argument, NULL, 0 }, +#ifdef SVT_HEVC + { "svt", no_argument, NULL, 0 }, + { "no-svt", no_argument, NULL, 0 }, + { "svt-hme", no_argument, NULL, 0 }, + { "no-svt-hme", no_argument, NULL, 0 }, + { "svt-search-width", required_argument, NULL, 0 }, + { "svt-search-height", required_argument, NULL, 0 }, + { "svt-compressed-ten-bit-format", no_argument, NULL, 0 }, + { "no-svt-compressed-ten-bit-format", no_argument, NULL, 0 }, + { "svt-speed-control", no_argument , NULL, 0 }, + { "no-svt-speed-control", no_argument , NULL, 0 }, + { "svt-preset-tuner", required_argument , NULL, 0 }, + { "svt-hierarchical-level", required_argument , NULL, 0 }, + { "svt-base-layer-switch-mode", required_argument , NULL, 0 }, + { "svt-pred-struct", required_argument , NULL, 0 }, + { "svt-fps-in-vps", no_argument , NULL, 0 }, + { "no-svt-fps-in-vps", no_argument , NULL, 0 }, +#endif { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, @@ -605,6 +623,19 @@ static void showHelp(x265_param *param) H1(" --recon-depth <integer> Bit-depth of reconstructed raw image file. Defaults to input bit depth, or 8 if Y4M\n"); H1(" --recon-y4m-exec <string> pipe reconstructed frames to Y4M viewer, ex:\"ffplay -i pipe:0 -autoexit\"\n"); H0(" --lowpass-dct Use low-pass subband dct approximation. Default %s\n", OPT(param->bLowPassDct)); +#ifdef SVT_HEVC + H0(" --[no]svt Enable SVT HEVC encoder %s\n", OPT(param->bEnableSvtHevc)); + H0(" --[no-]svt-hme Enable Hierarchial motion estimation(HME) in SVT HEVC encoder \n"); + H0(" --svt-search-width Motion estimation search area width for SVT HEVC encoder \n"); + H0(" --svt-search-height Motion estimation search area height for SVT HEVC encoder \n"); + H0(" --[no-]svt-compressed-ten-bit-format Enable 8+2 encoding mode for 10bit input in SVT HEVC encoder \n"); + H0(" --[no-]svt-speed-control Enable speed control functionality to achieve real time encoding speed for SVT HEVC encoder \n"); + H0(" --svt-preset-tuner Enable additional faster presets of SVT; This only has to be used on top of x265's ultrafast preset. Accepts values in the range of 0-2 \n"); + H0(" --svt-hierarchical-level Hierarchical layer for SVT-HEVC encoder; Accepts inputs in the range 0-3 \n"); + H0(" --svt-base-layer-switch-mode Select whether B/P slice should be used in base layer for SVT-HEVC encoder. 0-Use B-frames; 1-Use P frames in the base layer \n"); + H0(" --svt-pred-struct Select pred structure for SVT HEVC encoder; Accepts inputs in the range 0-2 \n"); + H0(" --[no-]svt-fps-in-vps Enable VPS timing info for SVT HEVC encoder \n"); +#endif H1("\nExecutable return codes:\n"); H1(" 0 - encode successful\n"); H1(" 1 - unable to parse command line\n");