Projects
Essentials
x265
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 31
View file
x265.changes
Changed
@@ -1,4 +1,53 @@ ------------------------------------------------------------------- +Fri Feb 1 00:32:50 UTC 2019 - antonio.larrosa@gmail.com + +- Support 10 and 12 bit color depths + +- Update to version 3.0 + New features + * option:: '--dolby-vision-profile <integer|float>' generates + bitstreams confirming to the specified Dolby Vision profile. + Currently profile 5, profile 8.1 and profile 8.2 enabled, + Default 0 (disabled) + * option:: '--dolby-vision-rpu' File containing Dolby Vision RPU + metadata. If given, x265's Dolby Vision metadata parser will + fill the RPU field of input pictures with the metadata read + from the file. The library will interleave access units with + RPUs in the bitstream. Default NULL (disabled). + * option:: '--zonefile <filename>' specifies a text file which + contains the boundaries of the zones where each of zones are + configurable. + * option:: '--qp-adaptation-range' Delta-QP range by QP + adaptation based on a psycho-visual model. Default 1.0. + * option:: '--refine-ctu-distortion <0/1>' store/normalize ctu + distortion in analysis-save/load. Default 0. + * Experimental feature option:: '--hevc-aq' enables adaptive + quantization. It scales the quantization step size according + to the spatial activity of one coding unit relative to frame + average spatial activity. This AQ method utilizes the minimum + variance of sub-unit in each coding unit to represent the + coding unit's spatial complexity. + Encoder enhancements + * Preset: change param defaults for veryslow and slower preset. + Replace slower preset with defaults used in veryslow preset + and change param defaults in veryslow preset as per + experimental results. + * AQ: change default AQ mode to auto-variance + * Cutree offset reuse: restricted to analysis reuse-level 10 for + analysis-save -> analysis-load + * Tune: introduce --tune animation option which improves encode + quality for animated content + * Reuse CU depth for B frame and allow I, P frame to follow + x265 depth decision + Bug fixes + * RC: fix rowStat computation in const-vbv + * Dynamic-refine: fix memory reset size. + * Fix linking issue on non x86 platform + * Encoder: Do not include CLL SEI message if empty + * Fix build error in VMAF lib +- Rebase x265-fix_enable512.patch + +------------------------------------------------------------------- Tue Oct 9 20:03:53 UTC 2018 - aloisio@gmx.com - Update to version 2.9
View file
x265.spec
Changed
@@ -1,10 +1,10 @@ # based on the spec file from https://build.opensuse.org/package/view_file/home:Simmphonie/libx265/ Name: x265 -%define soname 165 +%define soname 169 %define libname lib%{name} %define libsoname %{libname}-%{soname} -Version: 2.9 +Version: 3.0 Release: 0 License: GPL-2.0+ Summary: A free h265/HEVC encoder - encoder binary @@ -57,14 +57,52 @@ %build -%if 0%{?suse_version} < 1500 -cd source -%else -%define __builddir ./source/build +SOURCE_DIR="$PWD"/source +COMMON_FLAGS="-DENABLE_TESTS=OFF -DENABLE_PIC=ON" +HIGH_BIT_DEPTH_FLAGS="-DENABLE_CLI=OFF -DENABLE_SHARED=OFF -DEXPORT_C_API=OFF -DHIGH_BIT_DEPTH=ON" + +%if 0%{?suse_version} >= 1500 %define __sourcedir ./source + +# Build 10bit depth version of the library +%define __builddir ./source/build-10bit +%cmake $COMMON_FLAGS $HIGH_BIT_DEPTH_FLAGS \ +%ifarch i586 + -DENABLE_ASSEMBLY=OFF +%endif + +make %{?_smp_mflags} +cd ../.. + +# Build 12bit depth version of the library +%define __builddir ./source/build-12bit +%cmake $COMMON_FLAGS $HIGH_BIT_DEPTH_FLAGS -DMAIN12=ON \ +%ifarch i586 + -DENABLE_ASSEMBLY=OFF +%endif + +make %{?_smp_mflags} +cd ../.. + +mv source/build-10bit/libx265.a source/build-10bit/libx265_main10.a +mv source/build-12bit/libx265.a source/build-12bit/libx265_main12.a + +# Build general version of the library linking in the 10/12bit depth versions +%define __builddir ./source/build +%cmake -DENABLE_TESTS=OFF \ + -DENABLE_PIC=ON \ + -DENABLE_CLI=ON \ + -DLINKED_10BIT=ON \ + -DLINKED_12BIT=ON \ + -DEXTRA_LINK_FLAGS="-L$SOURCE_DIR/build-10bit -L$SOURCE_DIR/build-12bit" \ + -DEXTRA_LIB="x265_main10.a;x265_main12.a" + +%else +cd source +%cmake $COMMON_FLAGS %endif -%cmake -DENABLE_TESTS=OFF make %{?_smp_mflags} +cd ../../ %install %if 0%{?suse_version} < 1500
View file
x265-fix_enable512.patch
Changed
@@ -12,7 +12,7 @@ #if X265_ARCH_X86 extern "C" { -@@ -123,10 +128,6 @@ uint64_t PFX(cpu_xgetbv)(int xcr); +@@ -123,11 +128,6 @@ uint64_t PFX(cpu_xgetbv)(int xcr); #pragma warning(disable: 4309) // truncation of constant value #endif @@ -20,6 +20,7 @@ -{ - return(enable512); -} +- uint32_t cpu_detect(bool benableavx512 ) {
View file
baselibs.conf
Changed
@@ -1,1 +1,1 @@ -libx265-151 +libx265-169
View file
x265_2.9.tar.gz/.hg_archival.txt -> x265_3.0.tar.gz/.hg_archival.txt
Changed
@@ -1,4 +1,4 @@ repo: 09fe40627f03a0f9c3e6ac78b22ac93da23f9fdf -node: f9681d731f2e56c2ca185cec10daece5939bee07 +node: 72188bd2f03447e71e789a5fd2f10364bb232c2c branch: stable -tag: 2.9 +tag: 3.0
View file
x265_2.9.tar.gz/.hgtags -> x265_3.0.tar.gz/.hgtags
Changed
@@ -27,3 +27,8 @@ 0e9ea76945c89962cd46cee6537586e2054b2935 2.6 e41a9bf2bac4a7af2bec2bbadf91e63752d320ef 2.7 a158a3a029663133455268e2a63ae6b0af2df720 2.8 +f9681d731f2e56c2ca185cec10daece5939bee07 2.9 +bad4e598cac7cdd3df4623c68c91299c620471bd 3.0-rc +bad4e598cac7cdd3df4623c68c91299c620471bd 3.0-rc +0000000000000000000000000000000000000000 3.0-rc +1307fd7b2b9984f45179db01432305a416713049 3.0_RC
View file
x265_2.9.tar.gz/doc/reST/cli.rst -> x265_3.0.tar.gz/doc/reST/cli.rst
Changed
@@ -388,7 +388,7 @@ be applied after :option:`--preset` but before all other parameters. Default none. See :ref:`tunings <tunings>` for more detail. - **Values:** psnr, ssim, grain, zero-latency, fast-decode. + **Values:** psnr, ssim, grain, zero-latency, fast-decode, animation. .. option:: --slices <integer> @@ -930,6 +930,14 @@ Reuse MV information received through API call. Currently receives information for AVC size and the accepted string input is "avc". Default is disabled. +.. option:: --refine-ctu-distortion <0/1> + + Store/normalize ctu distortion in analysis-save/load. + 0 - Disabled. + 1 - Save ctu distortion to the analysis file specified during analysis-save. + Load CTU distortion from the analysis file and normalize it across every frame during analysis-load. + Default 0. + .. option:: --scale-factor Factor by which input video is scaled down for analysis save mode. @@ -1506,7 +1514,7 @@ 0 - flush the encoder only when all the input pictures are over. 1 - flush all the frames even when the input is not over. slicetype decision may change with this option. - 2 - flush the slicetype decided frames only. + 2 - flush the slicetype decided frames only. Quality, rate control and rate distortion options ================================================= @@ -1622,8 +1630,8 @@ and not enough in flat areas. 0. disabled - 1. AQ enabled **(default)** - 2. AQ enabled with auto-variance + 1. AQ enabled + 2. AQ enabled with auto-variance **(default)** 3. AQ enabled with auto-variance and bias to dark scenes. This is recommended for 8-bit encodes or low-bitrate 10-bit encodes, to prevent color banding/blocking. @@ -1638,6 +1646,21 @@ Default 1.0. **Range of values:** 0.0 to 3.0 +.. option:: --hevc-aq + + Enable adaptive quantization + It scales the quantization step size according to the spatial activity of one + coding unit relative to frame average spatial activity. This AQ method utilizes + the minimum variance of sub-unit in each coding unit to represent the coding + units spatial complexity. + +.. option:: --qp-adaptation-range + + Delta-QP range by QP adaptation based on a psycho-visual model. + + Default 1.0. + **Range of values:** 1.0 to 6.0 + .. option:: --aq-motion, --no-aq-motion Adjust the AQ offsets based on the relative motion of each block with @@ -1818,6 +1841,20 @@ If zones overlap, whichever comes later in the list takes precedence. Default none + + +.. option:: --zonefile <filename> + + Specify a text file which contains the boundaries of the zones where + each of zones are configurable. The format of each line is: + + <frame number> <options to be configured> + + The frame number indicates the beginning of a zone. The options + following this is applied until another zone begins. The reconfigurable + options can be spcified as --<feature name> <feature value> + + **CLI ONLY** Quantization Options ==================== @@ -2195,6 +2232,36 @@ Picture Timing SEI messages providing timing information to the decoder. Default disabled + +.. option:: --hrd-concat, --no-hrd-concat + + Set concantenation flag for the first keyframe in the HRD buffering period SEI. This + is to signal the decoder if splicing is performed during bitstream generation. + Recommended to enable this option during chunked encoding, except for the first chunk. + Default disabled. + +.. option:: --dolby-vision-profile <integer|float> + + Generate bitstreams confirming to the specified Dolby Vision profile, + note that 0x7C01 makes RPU appear to be an unspecified NAL type in + HEVC stream. If BL is backward compatible, Dolby Vision single + layer VES will be equivalent to a backward compatible BL VES on legacy + device as RPU will be ignored. + + The value is specified as a float or as an integer with the profile times 10, + for example profile 5 is specified as "5" or "5.0" or "50". + + Currently only profile 5, profile 8.1 and profile 8.2 enabled, Default 0 (disabled) + +.. option:: --dolby-vision-rpu <filename> + + File containing Dolby Vision RPU metadata. If given, x265's Dolby Vision + metadata parser will fill the RPU field of input pictures with the metadata + read from the file. The library will interleave access units with RPUs in the + bitstream. Default NULL (disabled). + + **CLI ONLY** + .. option:: --info, --no-info Emit an informational SEI with the stream headers which describes
View file
x265_2.9.tar.gz/doc/reST/presets.rst -> x265_3.0.tar.gz/doc/reST/presets.rst
Changed
@@ -43,33 +43,33 @@ +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | b-adapt | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| rc-lookahead | 5 | 10 | 15 | 15 | 15 | 20 | 25 | 30 | 40 | 60 | +| rc-lookahead | 5 | 10 | 15 | 15 | 15 | 20 | 25 | 40 | 40 | 60 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| lookahead-slices| 8 | 8 | 8 | 8 | 8 | 8 | 4 | 4 | 1 | 1 | +| lookahead-slices| 8 | 8 | 8 | 8 | 8 | 8 | 4 | 1 | 1 | 1 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | scenecut | 0 | 40 | 40 | 40 | 40 | 40 | 40 | 40 | 40 | 40 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| ref | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 5 | +| ref | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 5 | 5 | 5 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| limit-refs | 0 | 0 | 3 | 3 | 3 | 3 | 3 | 2 | 1 | 0 | +| limit-refs | 0 | 0 | 3 | 3 | 3 | 3 | 3 | 1 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | me | dia | hex | hex | hex | hex | hex | star | star | star | star | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | merange | 57 | 57 | 57 | 57 | 57 | 57 | 57 | 57 | 57 | 92 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| subme | 0 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 5 | +| subme | 0 | 1 | 1 | 2 | 2 | 2 | 3 | 4 | 4 | 5 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | rect | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | amp | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| limit-modes | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | +| limit-modes | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| max-merge | 2 | 2 | 2 | 2 | 2 | 2 | 3 | 3 | 4 | 5 | +| max-merge | 2 | 2 | 2 | 2 | 2 | 2 | 3 | 4 | 5 | 5 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | early-skip | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| recursion-skip | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| recursion-skip | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | fast-intra | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ @@ -83,7 +83,7 @@ +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | weightb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| aq-mode | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +| aq-mode | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | cuTree | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ @@ -91,11 +91,11 @@ +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ | rdoq-level | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| tu-intra | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 | +| tu-intra | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 3 | 3 | 4 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| tu-inter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 | +| tu-inter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 3 | 3 | 4 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ -| limit-tu | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 4 | 0 | +| limit-tu | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | +-----------------+-----+-----+-----+-----+-----+-----+------+------+------+------+ .. _tunings: @@ -128,6 +128,8 @@ +--------------+-----------------------------------------------------+ | zerolatency | no lookahead, no B frames, no cutree | +--------------+-----------------------------------------------------+ +| animation | improves encode quality for animated content | ++--------------+-----------------------------------------------------+ @@ -203,3 +205,14 @@ x265 performance. If you can tolerate any latency on the encoder, you can increase performance by increasing the number of frame threads. Each additional frame thread adds one frame of latency. + +Animation +~~~~~~~~~ + +:option:`--tune` *animation* adjusts encoder settings to optimize the encode +quality for animation content without impacting the encode speed. This is done by: + + * :option:`--psy-rd` 0.4 + * :option:`--aq-strength` 0.4 + * :option:`--deblock` 1:1 + * :option:`--bframes` Increase by 2 \ No newline at end of file
View file
x265_2.9.tar.gz/doc/reST/releasenotes.rst -> x265_3.0.tar.gz/doc/reST/releasenotes.rst
Changed
@@ -1,6 +1,43 @@ ************* Release Notes ************* +Version 3.0 +=========== + +Release date - 23/01/2019 + +New features +------------- +1. option:: '--dolby-vision-profile <integer|float>' generates bitstreams confirming to the specified Dolby Vision profile. Currently profile 5, profile 8.1 and profile 8.2 enabled, Default 0 (disabled) + +2. option:: '--dolby-vision-rpu' File containing Dolby Vision RPU metadata. If given, x265's Dolby Vision metadata parser will fill the RPU field of input pictures with the metadata + read from the file. The library will interleave access units with RPUs in the bitstream. Default NULL (disabled). + +3. option:: '--zonefile <filename>' specifies a text file which contains the boundaries of the zones where each of zones are configurable. + +4. option:: '--qp-adaptation-range' Delta-QP range by QP adaptation based on a psycho-visual model. Default 1.0. + +5. option:: '--refine-ctu-distortion <0/1>' store/normalize ctu distortion in analysis-save/load. Default 0. + +6. Experimental feature option:: '--hevc-aq' enables adaptive quantization + It scales the quantization step size according to the spatial activity of one coding unit relative to frame average spatial activity. This AQ method utilizes + the minimum variance of sub-unit in each coding unit to represent the coding unit’s spatial complexity. + +Encoder enhancements +-------------------- +1. Preset: change param defaults for veryslow and slower preset. Replace slower preset with defaults used in veryslow preset and change param defaults in veryslow preset as per experimental results. +2. AQ: change default AQ mode to auto-variance +3. Cutree offset reuse: restricted to analysis reuse-level 10 for analysis-save -> analysis-load +4. Tune: introduce --tune animation option which improves encode quality for animated content +5. Reuse CU depth for B frame and allow I, P frame to follow x265 depth decision + +Bug fixes +--------- +1. RC: fix rowStat computation in const-vbv +2. Dynamic-refine: fix memory reset size. +3. Fix Issue #442: linking issue on non x86 platform +4. Encoder: Do not include CLL SEI message if empty +5. Fix issue #441 build error in VMAF lib Version 2.9 ===========
View file
x265_2.9.tar.gz/source/CMakeLists.txt -> x265_3.0.tar.gz/source/CMakeLists.txt
Changed
@@ -29,7 +29,7 @@ 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 165) +set(X265_BUILD 169) configure_file("${PROJECT_SOURCE_DIR}/x265.def.in" "${PROJECT_BINARY_DIR}/x265.def") configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in" @@ -200,6 +200,9 @@ if(GCC) add_definitions(-Wall -Wextra -Wshadow) add_definitions(-D__STDC_LIMIT_MACROS=1) + if(NOT INTEL_CXX AND NOT CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0) + add_definitions(-Wno-class-memaccess) + endif() if(ENABLE_HDR10_PLUS) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8") message(FATAL_ERROR "gcc version above 4.8 required to support hdr10plus") @@ -572,10 +575,9 @@ # often breaks them string(REPLACE "<FLAGS>" "" CMAKE_RC_COMPILE_OBJECT "${CMAKE_RC_COMPILE_OBJECT}") string(REPLACE "<DEFINES>" "" CMAKE_RC_COMPILE_OBJECT "${CMAKE_RC_COMPILE_OBJECT}") - # convert X265_LATEST_TAG (ex: 0.7) and X265_TAG_DISTANCE (ex: 103) to # @X265_VERSION_MAJOR@,@X265_VERSION_MINOR@,@X265_BRANCH_ID@,@X265_TAG_DISTANCE@ - string(REPLACE "." ";" VERSION_LIST "${X265_LATEST_TAG}") + string(REGEX MATCHALL "([0-9]+)" VERSION_LIST "${X265_LATEST_TAG}") list(GET VERSION_LIST 0 X265_VERSION_MAJOR) list(GET VERSION_LIST 1 X265_VERSION_MINOR) set(X265_BRANCH_ID 0) # TODO: 0 - stable, 1 - default or other
View file
x265_2.9.tar.gz/source/common/cpu.cpp -> x265_3.0.tar.gz/source/common/cpu.cpp
Changed
@@ -127,6 +127,7 @@ { return(enable512); } + uint32_t cpu_detect(bool benableavx512 ) {
View file
x265_2.9.tar.gz/source/common/cudata.cpp -> x265_3.0.tar.gz/source/common/cudata.cpp
Changed
@@ -193,6 +193,7 @@ uint8_t *charBuf = dataPool.charMemBlock + (m_numPartitions * (BytesPerPartition - 4)) * instance; m_qp = (int8_t*)charBuf; charBuf += m_numPartitions; + m_qpAnalysis = (int8_t*)charBuf; charBuf += m_numPartitions; m_log2CUSize = charBuf; charBuf += m_numPartitions; m_lumaIntraDir = charBuf; charBuf += m_numPartitions; m_tqBypass = charBuf; charBuf += m_numPartitions; @@ -233,6 +234,7 @@ uint8_t *charBuf = dataPool.charMemBlock + (m_numPartitions * BytesPerPartition) * instance; m_qp = (int8_t*)charBuf; charBuf += m_numPartitions; + m_qpAnalysis = (int8_t*)charBuf; charBuf += m_numPartitions; m_log2CUSize = charBuf; charBuf += m_numPartitions; m_lumaIntraDir = charBuf; charBuf += m_numPartitions; m_tqBypass = charBuf; charBuf += m_numPartitions; @@ -291,6 +293,7 @@ /* sequential memsets */ m_partSet((uint8_t*)m_qp, (uint8_t)qp); + m_partSet((uint8_t*)m_qpAnalysis, (uint8_t)qp); m_partSet(m_log2CUSize, (uint8_t)m_slice->m_param->maxLog2CUSize); m_partSet(m_lumaIntraDir, (uint8_t)ALL_IDX); m_partSet(m_chromaIntraDir, (uint8_t)ALL_IDX); @@ -304,7 +307,7 @@ X265_CHECK(!(frame.m_encData->m_param->bLossless && !m_slice->m_pps->bTransquantBypassEnabled), "lossless enabled without TQbypass in PPS\n"); /* initialize the remaining CU data in one memset */ - memset(m_cuDepth, 0, (frame.m_param->internalCsp == X265_CSP_I400 ? BytesPerPartition - 11 : BytesPerPartition - 7) * m_numPartitions); + memset(m_cuDepth, 0, (frame.m_param->internalCsp == X265_CSP_I400 ? BytesPerPartition - 12 : BytesPerPartition - 8) * m_numPartitions); for (int8_t i = 0; i < NUM_TU_DEPTH; i++) m_refTuDepth[i] = -1; @@ -344,6 +347,7 @@ X265_CHECK(m_numPartitions == cuGeom.numPartitions, "initSubCU() size mismatch\n"); m_partSet((uint8_t*)m_qp, (uint8_t)qp); + m_partSet((uint8_t*)m_qpAnalysis, (uint8_t)qp); m_partSet(m_log2CUSize, (uint8_t)cuGeom.log2CUSize); m_partSet(m_lumaIntraDir, (uint8_t)ALL_IDX); @@ -354,7 +358,7 @@ m_partSet(m_cuDepth, (uint8_t)cuGeom.depth); /* initialize the remaining CU data in one memset */ - memset(m_predMode, 0, (ctu.m_chromaFormat == X265_CSP_I400 ? BytesPerPartition - 12 : BytesPerPartition - 8) * m_numPartitions); + memset(m_predMode, 0, (ctu.m_chromaFormat == X265_CSP_I400 ? BytesPerPartition - 13 : BytesPerPartition - 9) * m_numPartitions); memset(m_distortion, 0, m_numPartitions * sizeof(sse_t)); } @@ -369,6 +373,7 @@ m_bLastCuInSlice = subCU.m_bLastCuInSlice; m_subPartCopy((uint8_t*)m_qp + offset, (uint8_t*)subCU.m_qp); + m_subPartCopy((uint8_t*)m_qpAnalysis + offset, (uint8_t*)subCU.m_qpAnalysis); m_subPartCopy(m_log2CUSize + offset, subCU.m_log2CUSize); m_subPartCopy(m_lumaIntraDir + offset, subCU.m_lumaIntraDir); m_subPartCopy(m_tqBypass + offset, subCU.m_tqBypass); @@ -469,6 +474,7 @@ CUData& ctu = *m_encData->getPicCTU(m_cuAddr); m_partCopy((uint8_t*)ctu.m_qp + m_absIdxInCTU, (uint8_t*)m_qp); + m_partCopy((uint8_t*)ctu.m_qpAnalysis + m_absIdxInCTU, (uint8_t*)m_qpAnalysis); m_partCopy(ctu.m_log2CUSize + m_absIdxInCTU, m_log2CUSize); m_partCopy(ctu.m_lumaIntraDir + m_absIdxInCTU, m_lumaIntraDir); m_partCopy(ctu.m_tqBypass + m_absIdxInCTU, m_tqBypass); @@ -523,7 +529,11 @@ m_numPartitions = cuGeom.numPartitions; /* copy out all prediction info for this part */ - if (copyQp) m_partCopy((uint8_t*)m_qp, (uint8_t*)ctu.m_qp + m_absIdxInCTU); + if (copyQp) + { + m_partCopy((uint8_t*)m_qp, (uint8_t*)ctu.m_qp + m_absIdxInCTU); + m_partCopy((uint8_t*)m_qpAnalysis, (uint8_t*)ctu.m_qpAnalysis + m_absIdxInCTU); + } m_partCopy(m_log2CUSize, ctu.m_log2CUSize + m_absIdxInCTU); m_partCopy(m_lumaIntraDir, ctu.m_lumaIntraDir + m_absIdxInCTU); @@ -566,6 +576,7 @@ CUData& ctu = *m_encData->getPicCTU(m_cuAddr); m_partCopy((uint8_t*)ctu.m_qp + m_absIdxInCTU, (uint8_t*)m_qp); + m_partCopy((uint8_t*)ctu.m_qpAnalysis + m_absIdxInCTU, (uint8_t*)m_qpAnalysis); m_partCopy(ctu.m_transformSkip[0] + m_absIdxInCTU, m_transformSkip[0]); m_partCopy(ctu.m_predMode + m_absIdxInCTU, m_predMode); m_partCopy(ctu.m_tuDepth + m_absIdxInCTU, m_tuDepth);
View file
x265_2.9.tar.gz/source/common/cudata.h -> x265_3.0.tar.gz/source/common/cudata.h
Changed
@@ -191,6 +191,7 @@ /* Per-part data, stored contiguously */ int8_t* m_qp; // array of QP values + int8_t* m_qpAnalysis; // array of QP values for analysis reuse uint8_t* m_log2CUSize; // array of cu log2Size TODO: seems redundant to depth uint8_t* m_lumaIntraDir; // array of intra directions (luma) uint8_t* m_tqBypass; // array of CU lossless flags @@ -206,7 +207,7 @@ uint8_t* m_transformSkip[3]; // array of transform skipping flags per plane uint8_t* m_cbf[3]; // array of coded block flags (CBF) per plane uint8_t* m_chromaIntraDir; // array of intra directions (chroma) - enum { BytesPerPartition = 23 }; // combined sizeof() of all per-part data + enum { BytesPerPartition = 24 }; // combined sizeof() of all per-part data sse_t* m_distortion; coeff_t* m_trCoeff[3]; // transformed coefficient buffer per plane
View file
x265_2.9.tar.gz/source/common/frame.cpp -> x265_3.0.tar.gz/source/common/frame.cpp
Changed
@@ -44,6 +44,8 @@ m_param = NULL; m_userSEI.numPayloads = 0; m_userSEI.payloads = NULL; + m_rpu.payloadSize = 0; + m_rpu.payload = NULL; memset(&m_lowres, 0, sizeof(m_lowres)); m_rcData = NULL; m_encodeStartTime = 0; @@ -78,7 +80,7 @@ } } - if (param->bMVType == AVC_INFO) + if (param->bAnalysisType == AVC_INFO) { m_analysisData.wt = NULL; m_analysisData.intraData = NULL;
View file
x265_2.9.tar.gz/source/common/frame.h -> x265_3.0.tar.gz/source/common/frame.h
Changed
@@ -98,6 +98,7 @@ float* m_quantOffsets; // points to quantOffsets in x265_picture x265_sei m_userSEI; + x265_dolby_vision_rpu m_rpu; /* Frame Parallelism - notification between FrameEncoders of available motion reference rows */ ThreadSafeInteger* m_reconRowFlag; // flag of CTU rows completely reconstructed and extended for motion reference
View file
x265_2.9.tar.gz/source/common/framedata.cpp -> x265_3.0.tar.gz/source/common/framedata.cpp
Changed
@@ -83,9 +83,9 @@ memset(m_rowStat, 0, sps.numCuInHeight * sizeof(*m_rowStat)); if (m_param->bDynamicRefine) { - memset(m_picCTU->m_collectCURd, 0, MAX_NUM_DYN_REFINE * sizeof(uint64_t)); - memset(m_picCTU->m_collectCUVariance, 0, MAX_NUM_DYN_REFINE * sizeof(uint32_t)); - memset(m_picCTU->m_collectCUCount, 0, MAX_NUM_DYN_REFINE * sizeof(uint32_t)); + memset(m_picCTU->m_collectCURd, 0, MAX_NUM_DYN_REFINE * sps.numCUsInFrame * sizeof(uint64_t)); + memset(m_picCTU->m_collectCUVariance, 0, MAX_NUM_DYN_REFINE * sps.numCUsInFrame * sizeof(uint32_t)); + memset(m_picCTU->m_collectCUCount, 0, MAX_NUM_DYN_REFINE * sps.numCUsInFrame * sizeof(uint32_t)); } }
View file
x265_2.9.tar.gz/source/common/lowres.cpp -> x265_3.0.tar.gz/source/common/lowres.cpp
Changed
@@ -2,6 +2,7 @@ * Copyright (C) 2013-2017 MulticoreWare, Inc * * Authors: Gopu Govindaswamy <gopu@multicorewareinc.com> + * Ashok Kumar Mishra <ashok@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 @@ -27,10 +28,31 @@ using namespace X265_NS; +bool PicQPAdaptationLayer::create(uint32_t width, uint32_t height, uint32_t partWidth, uint32_t partHeight, uint32_t numAQPartInWidthExt, uint32_t numAQPartInHeightExt) +{ + aqPartWidth = partWidth; + aqPartHeight = partHeight; + numAQPartInWidth = (width + partWidth - 1) / partWidth; + numAQPartInHeight = (height + partHeight - 1) / partHeight; + + CHECKED_MALLOC_ZERO(dActivity, double, numAQPartInWidthExt * numAQPartInHeightExt); + CHECKED_MALLOC_ZERO(dQpOffset, double, numAQPartInWidthExt * numAQPartInHeightExt); + CHECKED_MALLOC_ZERO(dCuTreeOffset, double, numAQPartInWidthExt * numAQPartInHeightExt); + + if (bQpSize) + CHECKED_MALLOC_ZERO(dCuTreeOffset8x8, double, numAQPartInWidthExt * numAQPartInHeightExt); + + return true; +fail: + return false; +} + bool Lowres::create(x265_param* param, PicYuv *origPic, uint32_t qgSize) { isLowres = true; bframes = param->bframes; + widthFullRes = origPic->m_picWidth; + heightFullRes = origPic->m_picHeight; width = origPic->m_picWidth / 2; lines = origPic->m_picHeight / 2; lumaStride = width + 2 * origPic->m_lumaMarginX; @@ -49,7 +71,7 @@ size_t planesize = lumaStride * (lines + 2 * origPic->m_lumaMarginY); size_t padoffset = lumaStride * origPic->m_lumaMarginY + origPic->m_lumaMarginX; - if (!!param->rc.aqMode) + if (!!param->rc.aqMode || !!param->rc.hevcAq) { CHECKED_MALLOC_ZERO(qpAqOffset, double, cuCountFullRes); CHECKED_MALLOC_ZERO(invQscaleFactor, int, cuCountFullRes); @@ -57,10 +79,50 @@ if (qgSize == 8) CHECKED_MALLOC_ZERO(invQscaleFactor8x8, int, cuCount); } + if (origPic->m_param->bAQMotion) CHECKED_MALLOC_ZERO(qpAqMotionOffset, double, cuCountFullRes); if (origPic->m_param->bDynamicRefine) CHECKED_MALLOC_ZERO(blockVariance, uint32_t, cuCountFullRes); + + if (!!param->rc.hevcAq) + { + m_maxCUSize = param->maxCUSize; + m_qgSize = qgSize; + + uint32_t partWidth, partHeight, nAQPartInWidth, nAQPartInHeight; + + pAQLayer = new PicQPAdaptationLayer[4]; + maxAQDepth = 0; + for (uint32_t d = 0; d < 4; d++) + { + int ctuSizeIdx = 6 - g_log2Size[param->maxCUSize]; + int aqDepth = g_log2Size[param->maxCUSize] - g_log2Size[qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + pAQLayer->minAQDepth = d; + partWidth = param->maxCUSize >> d; + partHeight = param->maxCUSize >> d; + + if (minAQSize[ctuSizeIdx] == d) + { + pAQLayer[d].bQpSize = true; + nAQPartInWidth = maxBlocksInRow * 2; + nAQPartInHeight = maxBlocksInCol * 2; + } + else + { + pAQLayer[d].bQpSize = false; + nAQPartInWidth = (origPic->m_picWidth + partWidth - 1) / partWidth; + nAQPartInHeight = (origPic->m_picHeight + partHeight - 1) / partHeight; + } + + maxAQDepth++; + + pAQLayer[d].create(origPic->m_picWidth, origPic->m_picHeight, partWidth, partHeight, nAQPartInWidth, nAQPartInHeight); + } + } CHECKED_MALLOC(propagateCost, uint16_t, cuCount); /* allocate lowres buffers */ @@ -130,6 +192,25 @@ X265_FREE(invQscaleFactor8x8); X265_FREE(qpAqMotionOffset); X265_FREE(blockVariance); + if (maxAQDepth > 0) + { + for (uint32_t d = 0; d < 4; d++) + { + int ctuSizeIdx = 6 - g_log2Size[m_maxCUSize]; + int aqDepth = g_log2Size[m_maxCUSize] - g_log2Size[m_qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + X265_FREE(pAQLayer[d].dActivity); + X265_FREE(pAQLayer[d].dQpOffset); + X265_FREE(pAQLayer[d].dCuTreeOffset); + + if (pAQLayer[d].bQpSize == true) + X265_FREE(pAQLayer[d].dCuTreeOffset8x8); + } + + delete[] pAQLayer; + } } // (re) initialize lowres state void Lowres::init(PicYuv *origPic, int poc)
View file
x265_2.9.tar.gz/source/common/lowres.h -> x265_3.0.tar.gz/source/common/lowres.h
Changed
@@ -103,6 +103,49 @@ } }; +static const uint32_t aqLayerDepth[3][4][4] = { + { // ctu size 64 + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 }, + { 1, 1, 1, 0 }, + { 1, 1, 1, 1 } + }, + { // ctu size 32 + { 1, 1, 0, 0 }, + { 1, 1, 0, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 0 }, + }, + { // ctu size 16 + { 1, 0, 0, 0 }, + { 1, 1, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } + } +}; + +// min aq size for ctu size 64, 32 and 16 +static const uint32_t minAQSize[3] = { 3, 2, 1 }; + +struct PicQPAdaptationLayer +{ + uint32_t aqPartWidth; + uint32_t aqPartHeight; + uint32_t numAQPartInWidth; + uint32_t numAQPartInHeight; + uint32_t minAQDepth; + double* dActivity; + double* dQpOffset; + + double* dCuTreeOffset; + double* dCuTreeOffset8x8; + double dAvgActivity; + bool bQpSize; + + bool create(uint32_t width, uint32_t height, uint32_t aqPartWidth, uint32_t aqPartHeight, uint32_t numAQPartInWidthExt, uint32_t numAQPartInHeightExt); + void destroy(); +}; + /* lowres buffers, sizes and strides */ struct Lowres : public ReferencePlanes { @@ -154,6 +197,13 @@ uint64_t wp_sum[3]; /* cutree intermediate data */ + PicQPAdaptationLayer* pAQLayer; + uint32_t maxAQDepth; + uint32_t widthFullRes; + uint32_t heightFullRes; + uint32_t m_maxCUSize; + uint32_t m_qgSize; + uint16_t* propagateCost; double weightedCostDelta[X265_BFRAME_MAX + 2]; ReferencePlanes weightedRef[X265_BFRAME_MAX + 2];
View file
x265_2.9.tar.gz/source/common/param.cpp -> x265_3.0.tar.gz/source/common/param.cpp
Changed
@@ -158,6 +158,7 @@ param->radl = 0; param->chunkStart = 0; param->chunkEnd = 0; + param->bEnableHRDConcatFlag = 0; /* Intra Coding Tools */ param->bEnableConstrainedIntra = 0; @@ -231,9 +232,11 @@ param->rc.qpStep = 4; param->rc.rateControlMode = X265_RC_CRF; param->rc.qp = 32; - param->rc.aqMode = X265_AQ_VARIANCE; + param->rc.aqMode = X265_AQ_AUTO_VARIANCE; + param->rc.hevcAq = 0; param->rc.qgSize = 32; param->rc.aqStrength = 1.0; + param->rc.qpAdaptationRange = 1.0; param->rc.cuTree = 1; param->rc.rfConstantMax = 0; param->rc.rfConstantMin = 0; @@ -243,6 +246,7 @@ param->rc.complexityBlur = 20; param->rc.qblur = 0.5; param->rc.zoneCount = 0; + param->rc.zonefileCount = 0; param->rc.zones = NULL; param->rc.bEnableSlowFirstPass = 1; param->rc.bStrictCbr = 0; @@ -286,9 +290,9 @@ param->bAQMotion = 0; param->bHDROpt = 0; param->analysisReuseLevel = 5; - param->toneMapFile = NULL; param->bDhdr10opt = 0; + param->dolbyProfile = 0; param->bCTUInfo = 0; param->bUseRcStats = 0; param->scaleFactor = 0; @@ -296,6 +300,7 @@ param->interRefine = 0; param->bDynamicRefine = 0; param->mvRefine = 0; + param->ctuDistortionRefine = 0; param->bUseAnalysisFile = 1; param->csvfpt = NULL; param->forceFlush = 0; @@ -306,7 +311,7 @@ /* DCT Approximations */ param->bLowPassDct = 0; - param->bMVType = 0; + param->bAnalysisType = 0; param->bSingleSeiNal = 0; /* SEI messages */ @@ -348,6 +353,7 @@ param->limitReferences = 0; param->rc.aqStrength = 0.0; param->rc.aqMode = X265_AQ_NONE; + param->rc.hevcAq = 0; param->rc.qgSize = 32; param->bEnableFastIntra = 1; } @@ -365,6 +371,7 @@ param->limitReferences = 0; param->rc.aqStrength = 0.0; param->rc.aqMode = X265_AQ_NONE; + param->rc.hevcAq = 0; param->rc.qgSize = 32; param->bEnableSAO = 0; param->bEnableFastIntra = 1; @@ -420,21 +427,21 @@ param->bEnableWeightedBiPred = 1; param->bEnableAMP = 1; param->bEnableRectInter = 1; - param->lookaheadDepth = 30; + param->lookaheadDepth = 40; param->bframes = 8; - param->tuQTMaxInterDepth = 2; - param->tuQTMaxIntraDepth = 2; + param->tuQTMaxInterDepth = 3; + param->tuQTMaxIntraDepth = 3; param->rdLevel = 6; param->rdoqLevel = 2; param->psyRdoq = 1.0; - param->subpelRefine = 3; - param->maxNumMergeCand = 3; + param->subpelRefine = 4; + param->maxNumMergeCand = 4; param->searchMethod = X265_STAR_SEARCH; - param->maxNumReferences = 4; - param->limitReferences = 2; + param->maxNumReferences = 5; + param->limitReferences = 1; param->limitModes = 1; param->bIntraInBFrames = 1; - param->lookaheadSlices = 4; // limit parallelism as already enough work exists + param->lookaheadSlices = 0; // disabled for best quality param->limitTU = 4; } else if (!strcmp(preset, "veryslow")) @@ -450,14 +457,14 @@ param->rdoqLevel = 2; param->psyRdoq = 1.0; param->subpelRefine = 4; - param->maxNumMergeCand = 4; + param->maxNumMergeCand = 5; param->searchMethod = X265_STAR_SEARCH; param->maxNumReferences = 5; - param->limitReferences = 1; - param->limitModes = 1; + param->limitReferences = 0; + param->limitModes = 0; param->bIntraInBFrames = 1; param->lookaheadSlices = 0; // disabled for best quality - param->limitTU = 4; + param->limitTU = 0; } else if (!strcmp(preset, "placebo")) { @@ -525,6 +532,7 @@ param->rc.pbFactor = 1.0; param->rc.cuTree = 0; param->rc.aqMode = 0; + param->rc.hevcAq = 0; param->rc.qpStep = 1; param->rc.bEnableGrain = 1; param->bEnableRecursionSkip = 0; @@ -533,6 +541,14 @@ param->bEnableSAO = 0; param->rc.bEnableConstVbv = 1; } + else if (!strcmp(tune, "animation")) + { + param->bframes = (param->bframes + 2) >= param->lookaheadDepth? param->bframes : param->bframes + 2; + param->psyRd = 0.4; + param->rc.aqStrength = 0.4; + param->deblockingFilterBetaOffset = 1; + param->deblockingFilterTCOffset = 1; + } else return -1; } @@ -562,6 +578,120 @@ return x265_atoi(arg, bError); } +/* internal versions of string-to-int with additional error checking */ +#undef atoi +#undef atof +#define atoi(str) x265_atoi(str, bError) +#define atof(str) x265_atof(str, bError) +#define atobool(str) (x265_atobool(str, bError)) + +int x265_zone_param_parse(x265_param* p, const char* name, const char* value) +{ + bool bError = false; + char nameBuf[64]; + + if (!name) + return X265_PARAM_BAD_NAME; + + // skip -- prefix if provided + if (name[0] == '-' && name[1] == '-') + name += 2; + + // s/_/-/g + if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_')) + { + char *c; + strcpy(nameBuf, name); + while ((c = strchr(nameBuf, '_')) != 0) + *c = '-'; + + name = nameBuf; + } + + if (!strncmp(name, "no-", 3)) + { + name += 3; + value = !value || x265_atobool(value, bError) ? "false" : "true"; + } + else if (!strncmp(name, "no", 2)) + { + name += 2; + value = !value || x265_atobool(value, bError) ? "false" : "true"; + } + else if (!value) + value = "true"; + else if (value[0] == '=') + value++; + +#define OPT(STR) else if (!strcmp(name, STR)) +#define OPT2(STR1, STR2) else if (!strcmp(name, STR1) || !strcmp(name, STR2)) + + if (0); + OPT("ref") p->maxNumReferences = atoi(value); + OPT("fast-intra") p->bEnableFastIntra = atobool(value); + OPT("early-skip") p->bEnableEarlySkip = atobool(value); + OPT("rskip") p->bEnableRecursionSkip = atobool(value); + OPT("me")p->searchMethod = parseName(value, x265_motion_est_names, bError); + OPT("subme") p->subpelRefine = atoi(value); + OPT("merange") p->searchRange = atoi(value); + OPT("rect") p->bEnableRectInter = atobool(value); + OPT("amp") p->bEnableAMP = atobool(value); + OPT("max-merge") p->maxNumMergeCand = (uint32_t)atoi(value); + OPT("rd") p->rdLevel = atoi(value); + OPT("radl") p->radl = atoi(value); + OPT2("rdoq", "rdoq-level") + { + int bval = atobool(value); + if (bError || bval) + { + bError = false; + p->rdoqLevel = atoi(value); + } + else + p->rdoqLevel = 0; + } + OPT("b-intra") p->bIntraInBFrames = atobool(value); + OPT("scaling-list") p->scalingLists = strdup(value); + OPT("crf") + { + p->rc.rfConstant = atof(value); + p->rc.rateControlMode = X265_RC_CRF; + } + OPT("qp") + { + p->rc.qp = atoi(value); + p->rc.rateControlMode = X265_RC_CQP; + } + OPT("bitrate") + { + p->rc.bitrate = atoi(value); + p->rc.rateControlMode = X265_RC_ABR; + } + OPT("aq-mode") p->rc.aqMode = atoi(value); + OPT("aq-strength") p->rc.aqStrength = atof(value); + OPT("nr-intra") p->noiseReductionIntra = atoi(value); + OPT("nr-inter") p->noiseReductionInter = atoi(value); + OPT("limit-modes") p->limitModes = atobool(value); + OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value); + OPT("cu-lossless") p->bCULossless = atobool(value); + OPT("rd-refine") p->bEnableRdRefine = atobool(value); + OPT("limit-tu") p->limitTU = atoi(value); + OPT("tskip") p->bEnableTransformSkip = atobool(value); + OPT("tskip-fast") p->bEnableTSkipFast = atobool(value); + OPT("rdpenalty") p->rdPenalty = atoi(value); + OPT("dynamic-rd") p->dynamicRd = atof(value); + else + return X265_PARAM_BAD_NAME; + +#undef OPT +#undef OPT2 + + return bError ? X265_PARAM_BAD_VALUE : 0; +} + +#undef atobool +#undef atoi +#undef atof /* internal versions of string-to-int with additional error checking */ #undef atoi @@ -1023,15 +1153,19 @@ OPT("vbv-end") p->vbvBufferEnd = atof(value); OPT("vbv-end-fr-adj") p->vbvEndFrameAdjust = atof(value); OPT("copy-pic") p->bCopyPicToFrame = atobool(value); - OPT("refine-mv-type") + OPT("refine-analysis-type") { if (strcmp(strdup(value), "avc") == 0) { - p->bMVType = AVC_INFO; + p->bAnalysisType = AVC_INFO; + } + else if (strcmp(strdup(value), "hevc") == 0) + { + p->bAnalysisType = HEVC_INFO; } else if (strcmp(strdup(value), "off") == 0) { - p->bMVType = NO_INFO; + p->bAnalysisType = NO_INFO; } else { @@ -1050,6 +1184,19 @@ OPT("chunk-start") p->chunkStart = atoi(value); OPT("chunk-end") p->chunkEnd = atoi(value); OPT("nalu-file") p->naluFile = strdup(value); + OPT("dolby-vision-profile") + { + if (atof(value) < 10) + p->dolbyProfile = (int)(10 * atof(value) + .5); + else if (atoi(value) < 100) + p->dolbyProfile = atoi(value); + else + bError = true; + } + OPT("hrd-concat") p->bEnableHRDConcatFlag = atobool(value); + 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); else return X265_PARAM_BAD_NAME; } @@ -1294,6 +1441,8 @@ "Aq-Mode is out of range"); CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3, "Aq-Strength is out of range"); + CHECK(param->rc.qpAdaptationRange < 1.0f || param->rc.qpAdaptationRange > 6.0f, + "qp adaptation range is out of range"); CHECK(param->deblockingFilterTCOffset < -6 || param->deblockingFilterTCOffset > 6, "deblocking filter tC offset must be in the range of -6 to +6"); CHECK(param->deblockingFilterBetaOffset < -6 || param->deblockingFilterBetaOffset > 6, @@ -1405,8 +1554,21 @@ "Invalid refine-inter value, refine-inter levels 0 to 3 supported"); CHECK(param->intraRefine > 4 || param->intraRefine < 0, "Invalid refine-intra value, refine-intra levels 0 to 3 supported"); + CHECK(param->ctuDistortionRefine < 0 || param->ctuDistortionRefine > 1, + "Invalid refine-ctu-distortion value, must be either 0 or 1"); CHECK(param->maxAUSizeFactor < 0.5 || param->maxAUSizeFactor > 1.0, "Supported factor for controlling max AU size is from 0.5 to 1"); + CHECK((param->dolbyProfile != 0) && (param->dolbyProfile != 50) && (param->dolbyProfile != 81) && (param->dolbyProfile != 82), + "Unsupported Dolby Vision profile, only profile 5, profile 8.1 and profile 8.2 enabled"); + if (param->dolbyProfile) + { + CHECK((param->rc.vbvMaxBitrate <= 0 || param->rc.vbvBufferSize <= 0), "Dolby Vision requires VBV settings to enable HRD.\n"); + CHECK((param->internalBitDepth != 10), "Dolby Vision profile - 5, profile - 8.1 and profile - 8.2 is Main10 only\n"); + CHECK((param->internalCsp != X265_CSP_I420), "Dolby Vision profile - 5, profile - 8.1 and profile - 8.2 requires YCbCr 4:2:0 color space\n"); + + if (param->dolbyProfile == 81) + CHECK(!(param->masteringDisplayColorVolume), "Dolby Vision profile - 8.1 requires Mastering display color volume information\n"); + } #if !X86_64 CHECK(param->searchMethod == X265_SEA && (param->sourceWidth > 840 || param->sourceHeight > 480), "SEA motion search does not support resolutions greater than 480p in 32 bit build"); @@ -1557,8 +1719,12 @@ TOOLVAL(param->lookaheadSlices, "lslices=%d"); TOOLVAL(param->lookaheadThreads, "lthreads=%d") TOOLVAL(param->bCTUInfo, "ctu-info=%d"); - if (param->bMVType == AVC_INFO) - TOOLOPT(param->bMVType, "refine-mv-type=avc"); + if (param->bAnalysisType == AVC_INFO) + { + TOOLOPT(param->bAnalysisType, "refine-analysis-type=avc"); + } + else if (param->bAnalysisType == HEVC_INFO) + TOOLOPT(param->bAnalysisType, "refine-analysis-type=hevc"); TOOLOPT(param->bDynamicRefine, "dynamic-refine"); if (param->maxSlices > 1) TOOLVAL(param->maxSlices, "slices=%d"); @@ -1645,6 +1811,7 @@ s += sprintf(s, " lookahead-slices=%d", p->lookaheadSlices); s += sprintf(s, " scenecut=%d", p->scenecutThreshold); s += sprintf(s, " radl=%d", p->radl); + BOOL(p->bEnableHRDConcatFlag, "splice"); BOOL(p->bIntraRefresh, "intra-refresh"); s += sprintf(s, " ctu=%d", p->maxCUSize); s += sprintf(s, " min-cu-size=%d", p->minCUSize); @@ -1797,14 +1964,17 @@ s += sprintf(s, " refine-intra=%d", p->intraRefine); s += sprintf(s, " refine-inter=%d", p->interRefine); s += sprintf(s, " refine-mv=%d", p->mvRefine); + s += sprintf(s, " refine-ctu-distortion=%d", p->ctuDistortionRefine); BOOL(p->bLimitSAO, "limit-sao"); s += sprintf(s, " ctu-info=%d", p->bCTUInfo); BOOL(p->bLowPassDct, "lowpass-dct"); - s += sprintf(s, " refine-mv-type=%d", p->bMVType); + s += sprintf(s, " refine-analysis-type=%d", p->bAnalysisType); s += sprintf(s, " copy-pic=%d", p->bCopyPicToFrame); s += sprintf(s, " max-ausize-factor=%.1f", p->maxAUSizeFactor); BOOL(p->bDynamicRefine, "dynamic-refine"); BOOL(p->bSingleSeiNal, "single-sei"); + BOOL(p->rc.hevcAq, "hevc-aq"); + s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange); #undef BOOL return buf; }
View file
x265_2.9.tar.gz/source/common/param.h -> x265_3.0.tar.gz/source/common/param.h
Changed
@@ -51,6 +51,7 @@ int x265_param_default_preset(x265_param *, const char *preset, const char *tune); int x265_param_apply_profile(x265_param *, const char *profile); int x265_param_parse(x265_param *p, const char *name, const char *value); +int x265_zone_param_parse(x265_param* p, const char* name, const char* value); #define PARAM_NS X265_NS #endif }
View file
x265_2.9.tar.gz/source/common/quant.cpp -> x265_3.0.tar.gz/source/common/quant.cpp
Changed
@@ -723,6 +723,7 @@ X265_CHECK(coeffNum[cgScanPos] == 0, "count of coeff failure\n"); uint32_t scanPosBase = (cgScanPos << MLS_CG_SIZE); uint32_t blkPos = codeParams.scan[scanPosBase]; +#if X265_ARCH_X86 bool enable512 = detect512(); if (enable512) primitives.cu[log2TrSize - 2].psyRdoQuant(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); @@ -731,6 +732,10 @@ primitives.cu[log2TrSize - 2].psyRdoQuant_1p(m_resiDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost,blkPos); primitives.cu[log2TrSize - 2].psyRdoQuant_2p(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); } +#else + primitives.cu[log2TrSize - 2].psyRdoQuant_1p(m_resiDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, blkPos); + primitives.cu[log2TrSize - 2].psyRdoQuant_2p(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); +#endif } } else @@ -805,8 +810,8 @@ uint32_t blkPos = codeParams.scan[scanPosBase]; if (usePsyMask) { +#if X265_ARCH_X86 bool enable512 = detect512(); - if (enable512) primitives.cu[log2TrSize - 2].psyRdoQuant(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); else @@ -814,6 +819,10 @@ primitives.cu[log2TrSize - 2].psyRdoQuant_1p(m_resiDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, blkPos); primitives.cu[log2TrSize - 2].psyRdoQuant_2p(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); } +#else + primitives.cu[log2TrSize - 2].psyRdoQuant_1p(m_resiDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, blkPos); + primitives.cu[log2TrSize - 2].psyRdoQuant_2p(m_resiDctCoeff, m_fencDctCoeff, costUncoded, &totalUncodedCost, &totalRdCost, &psyScale, blkPos); +#endif blkPos = codeParams.scan[scanPosBase]; for (int y = 0; y < MLS_CG_SIZE; y++) {
View file
x265_2.9.tar.gz/source/encoder/analysis.cpp -> x265_3.0.tar.gz/source/encoder/analysis.cpp
Changed
@@ -140,6 +140,7 @@ m_slice = ctu.m_slice; m_frame = &frame; m_bChromaSa8d = m_param->rdLevel >= 3; + m_param = m_frame->m_param; #if _DEBUG || CHECKED_BUILD invalidateContexts(0); @@ -233,9 +234,9 @@ } else { - bool bCopyAnalysis = ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bMVType && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)); - bool BCompressInterCUrd0_4 = (m_param->bMVType && m_param->analysisReuseLevel >= 7 && m_param->rdLevel <= 4); - bool BCompressInterCUrd5_6 = (m_param->bMVType && m_param->analysisReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); + bool bCopyAnalysis = ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)); + bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel <= 4); + bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); bCopyAnalysis = bCopyAnalysis || BCompressInterCUrd0_4 || BCompressInterCUrd5_6; if (bCopyAnalysis) @@ -248,7 +249,7 @@ for (int list = 0; list < m_slice->isInterB() + 1; list++) memcpy(ctu.m_skipFlag[list], &m_frame->m_analysisData.modeFlag[list][posCTU], sizeof(uint8_t) * numPartition); - if ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !m_param->bMVType) + if ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !(m_param->bAnalysisType == AVC_INFO)) { x265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData; memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition); @@ -274,14 +275,15 @@ /* generate residual for entire CTU at once and copy to reconPic */ encodeResidue(ctu, cuGeom); } - else if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || ((m_param->bMVType == AVC_INFO) && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)) + else if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) || + ((m_param->bAnalysisType == AVC_INFO) && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int posCTU = ctu.m_cuAddr * numPartition; memcpy(ctu.m_cuDepth, &interDataCTU->depth[posCTU], sizeof(uint8_t) * numPartition); memcpy(ctu.m_predMode, &interDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition); memcpy(ctu.m_partSize, &interDataCTU->partSize[posCTU], sizeof(uint8_t) * numPartition); - if ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !(m_param->bMVType == AVC_INFO)) + if ((m_slice->m_sliceType == P_SLICE || m_param->bIntraInBFrames) && !(m_param->bAnalysisType == AVC_INFO)) { x265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData; memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[posCTU], sizeof(uint8_t) * numPartition); @@ -515,7 +517,7 @@ bool mightSplit = !(cuGeom.flags & CUGeom::LEAF); bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY); - bool bAlreadyDecided = m_param->intraRefine != 4 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] != (uint8_t)ALL_IDX; + bool bAlreadyDecided = m_param->intraRefine != 4 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] != (uint8_t)ALL_IDX && !(m_param->bAnalysisType == HEVC_INFO); bool bDecidedDepth = m_param->intraRefine != 4 && parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth; int split = 0; if (m_param->intraRefine && m_param->intraRefine != 4) @@ -1161,9 +1163,9 @@ PicYuv& reconPic = *m_frame->m_reconPic; SplitData splitCUData; - bool bHEVCBlockAnalysis = (m_param->bMVType && cuGeom.numPartitions > 16); + bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); - bool bNooffloading = !m_param->bMVType; + bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) { @@ -1298,7 +1300,7 @@ } } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs, if skip mode was not set above */ - if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bMVType && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) /* TODO: Re-evaluate if analysis load/save still works */ + if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) /* TODO: Re-evaluate if analysis load/save still works */ { /* Compute Merge Cost */ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -1308,7 +1310,7 @@ skipModes = (m_param->bEnableEarlySkip || m_refineLevel == 2) && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth } - if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bMVType && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { skipRecursion = md.bestMode->cu.isSkipped(0); if (mightSplit && depth >= minDepth && !skipRecursion) @@ -1319,7 +1321,7 @@ skipRecursion = complexityCheckCU(*md.bestMode); } } - if (m_param->bMVType && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) skipRecursion = true; /* Step 2. Evaluate each of the 4 split sub-blocks in series */ if (mightSplit && !skipRecursion) @@ -1376,7 +1378,7 @@ splitPred->sa8dCost = m_rdCost.calcRdSADCost((uint32_t)splitPred->distortion, splitPred->sa8dBits); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bMVType && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -1793,7 +1795,7 @@ } else { - if (m_param->bMVType && cuGeom.numPartitions <= 16) + if (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions <= 16) { qprdRefine(parentCTU, cuGeom, qp, qp); @@ -1854,9 +1856,9 @@ SplitData splitCUData; - bool bHEVCBlockAnalysis = (m_param->bMVType && cuGeom.numPartitions > 16); + bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); - bool bNooffloading = !m_param->bMVType; + bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) { @@ -1997,7 +1999,7 @@ } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs */ if ((mightNotSplit && !md.bestMode && !bCtuInfoCheck) || - (m_param->bMVType && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp); md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -2012,7 +2014,7 @@ if (m_param->bEnableRecursionSkip && depth && m_modeDepth[depth - 1].bestMode) skipRecursion = md.bestMode && !md.bestMode->cu.getQtRootCbf(0); } - if (m_param->bMVType && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) skipRecursion = true; // estimate split cost /* Step 2. Evaluate each of the 4 split sub-blocks in series */ @@ -2066,7 +2068,7 @@ checkDQPForSplitPred(*splitPred, cuGeom); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bMVType && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -2361,7 +2363,7 @@ } else { - if (m_param->bMVType && cuGeom.numPartitions <= 16) + if (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions <= 16) { qprdRefine(parentCTU, cuGeom, qp, qp); @@ -2422,7 +2424,7 @@ (m_refineLevel && cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param->minCUSize] + 1)))); td.split = split; - if (bDecidedDepth && mightNotSplit) + if ((bDecidedDepth && mightNotSplit) || (m_param->bAnalysisType == HEVC_INFO && parentCTU.m_cuDepth[cuGeom.absPartIdx] == 4)) { setLambdaFromQP(parentCTU, qp, lqp); @@ -2453,7 +2455,7 @@ for (uint32_t part = 0; part < numPU; part++) { PredictionUnit pu(mode.cu, cuGeom, part); - if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bMVType == AVC_INFO && m_param->analysisReuseLevel >= 7)) + if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int cuIdx = (mode.cu.m_cuAddr * parentCTU.m_numPartitions) + cuGeom.absPartIdx; @@ -2540,7 +2542,7 @@ checkDQPForSplitPred(*md.bestMode, cuGeom); } - if (m_param->bMVType && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) { for (int list = 0; list < m_slice->isInterB() + 1; list++) { @@ -2561,7 +2563,10 @@ if (m_refineLevel > 1 || (m_refineLevel && parentCTU.m_predMode[cuGeom.absPartIdx] == MODE_SKIP && !mode.cu.isSkipped(0))) { - m_evaluateInter = 1; + if (parentCTU.m_cuDepth[cuGeom.absPartIdx] < 4 && mightNotSplit) + m_evaluateInter = 1; + else + bDecidedDepth = true; m_param->rdLevel > 4 ? compressInterCU_rd5_6(parentCTU, cuGeom, qp) : compressInterCU_rd0_4(parentCTU, cuGeom, qp); m_evaluateInter = 0; } @@ -3555,12 +3560,41 @@ return cuVariance / cnt; } +double Analysis::aqQPOffset(const CUData& ctu, const CUGeom& cuGeom) +{ + uint32_t aqDepth = X265_MIN(cuGeom.depth, m_frame->m_lowres.maxAQDepth - 1); + PicQPAdaptationLayer* pQPLayer = &m_frame->m_lowres.pAQLayer[aqDepth]; + + uint32_t aqPosX = (ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]) / pQPLayer->aqPartWidth; + uint32_t aqPosY = (ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]) / pQPLayer->aqPartHeight; + + uint32_t aqStride = pQPLayer->numAQPartInWidth; + + double dQpOffset = pQPLayer->dQpOffset[aqPosY * aqStride + aqPosX]; + return dQpOffset; +} + +double Analysis::cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom) +{ + uint32_t aqDepth = X265_MIN(cuGeom.depth, m_frame->m_lowres.maxAQDepth - 1); + PicQPAdaptationLayer* pcAQLayer = &m_frame->m_lowres.pAQLayer[aqDepth]; + + uint32_t aqPosX = (ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]) / pcAQLayer->aqPartWidth; + uint32_t aqPosY = (ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]) / pcAQLayer->aqPartHeight; + + uint32_t aqStride = pcAQLayer->numAQPartInWidth; + + double dQpOffset = pcAQLayer->dCuTreeOffset[aqPosY * aqStride + aqPosX]; + return dQpOffset; +} + int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck, double baseQp) { FrameData& curEncData = *m_frame->m_encData; double qp = baseQp >= 0 ? baseQp : curEncData.m_cuStat[ctu.m_cuAddr].baseQp; + bool bCuTreeOffset = IS_REFERENCED(m_frame) && m_param->rc.cuTree && !complexCheck; - if (m_param->analysisMultiPassDistortion && m_param->rc.bStatRead) + if ((m_param->analysisMultiPassDistortion && m_param->rc.bStatRead) || (m_param->ctuDistortionRefine && m_param->analysisLoad)) { x265_analysis_distortion_data* distortionData = m_frame->m_analysisData.distortionData; if ((distortionData->threshold[ctu.m_cuAddr] < 0.9 || distortionData->threshold[ctu.m_cuAddr] > 1.1) @@ -3568,40 +3602,68 @@ qp += distortionData->offset[ctu.m_cuAddr]; } - int loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16; - - /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */ - bool isReferenced = IS_REFERENCED(m_frame); - double *qpoffs = (isReferenced && m_param->rc.cuTree && !complexCheck) ? m_frame->m_lowres.qpCuTreeOffset : - m_frame->m_lowres.qpAqOffset; - if (qpoffs) - { - uint32_t width = m_frame->m_fencPic->m_picWidth; - uint32_t height = m_frame->m_fencPic->m_picHeight; - uint32_t block_x = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]; - uint32_t block_y = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]; - uint32_t maxCols = (m_frame->m_fencPic->m_picWidth + (loopIncr - 1)) / loopIncr; - uint32_t blockSize = m_param->maxCUSize >> cuGeom.depth; - double qp_offset = 0; - uint32_t cnt = 0; - for (uint32_t block_yy = block_y; block_yy < block_y + blockSize && block_yy < height; block_yy += loopIncr) - { - for (uint32_t block_xx = block_x; block_xx < block_x + blockSize && block_xx < width; block_xx += loopIncr) - { - uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr); - qp_offset += qpoffs[idx]; - cnt++; + if (m_param->analysisLoad && m_param->analysisReuseLevel == 10 && m_param->rc.cuTree) + { + int cuIdx = (ctu.m_cuAddr * ctu.m_numPartitions) + cuGeom.absPartIdx; + if (ctu.m_slice->m_sliceType == I_SLICE) + return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + ((x265_analysis_intra_data*)m_frame->m_analysisData.intraData)->cuQPOff[cuIdx])); + else + return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + ((x265_analysis_inter_data*)m_frame->m_analysisData.interData)->cuQPOff[cuIdx])); + } + if (m_param->rc.hevcAq) + { + /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */ + double dQpOffset = 0; + if (bCuTreeOffset) + { + dQpOffset = cuTreeQPOffset(ctu, cuGeom); + } + else + { + dQpOffset = aqQPOffset(ctu, cuGeom); + if (complexCheck) + { + int32_t offset = (int32_t)(dQpOffset * 100 + .5); + double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5)); + int32_t max_threshold = (int32_t)(threshold * 100 + .5); + return (offset < max_threshold); } } - - qp_offset /= cnt; - qp += qp_offset; - if (complexCheck) - { - int32_t offset = (int32_t)(qp_offset * 100 + .5); - double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5)); - int32_t max_threshold = (int32_t)(threshold * 100 + .5); - return (offset < max_threshold); + qp += dQpOffset; + } + else + { + int loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16; + /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */ + double *qpoffs = bCuTreeOffset ? m_frame->m_lowres.qpCuTreeOffset : m_frame->m_lowres.qpAqOffset; + if (qpoffs) + { + uint32_t width = m_frame->m_fencPic->m_picWidth; + uint32_t height = m_frame->m_fencPic->m_picHeight; + uint32_t block_x = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]; + uint32_t block_y = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]; + uint32_t maxCols = (m_frame->m_fencPic->m_picWidth + (loopIncr - 1)) / loopIncr; + uint32_t blockSize = m_param->maxCUSize >> cuGeom.depth; + double dQpOffset = 0; + uint32_t cnt = 0; + for (uint32_t block_yy = block_y; block_yy < block_y + blockSize && block_yy < height; block_yy += loopIncr) + { + for (uint32_t block_xx = block_x; block_xx < block_x + blockSize && block_xx < width; block_xx += loopIncr) + { + uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr); + dQpOffset += qpoffs[idx]; + cnt++; + } + } + dQpOffset /= cnt; + qp += dQpOffset; + if (complexCheck) + { + int32_t offset = (int32_t)(dQpOffset * 100 + .5); + double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5)); + int32_t max_threshold = (int32_t)(threshold * 100 + .5); + return (offset < max_threshold); + } } }
View file
x265_2.9.tar.gz/source/encoder/analysis.h -> x265_3.0.tar.gz/source/encoder/analysis.h
Changed
@@ -201,7 +201,8 @@ void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData); void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData); - + double aqQPOffset(const CUData& ctu, const CUGeom& cuGeom); + double cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom); void calculateNormFactor(CUData& ctu, int qp); void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);
View file
x265_2.9.tar.gz/source/encoder/api.cpp -> x265_3.0.tar.gz/source/encoder/api.cpp
Changed
@@ -94,6 +94,7 @@ Encoder* encoder = NULL; x265_param* param = PARAM_NS::x265_param_alloc(); x265_param* latestParam = PARAM_NS::x265_param_alloc(); + x265_param* zoneParam = PARAM_NS::x265_param_alloc(); if (!param || !latestParam) goto fail; @@ -126,6 +127,13 @@ } encoder->create(); + + memcpy(zoneParam, param, sizeof(x265_param)); + for (int i = 0; i < param->rc.zonefileCount; i++) + { + encoder->configureZone(zoneParam, param->rc.zones[i].zoneParam); + } + /* Try to open CSV file handle */ if (encoder->m_param->csvfn) { @@ -213,6 +221,7 @@ } else { + encoder->configure(encoder->m_latestParam); if (encoder->m_latestParam->scalingLists && encoder->m_latestParam->scalingLists != encoder->m_param->scalingLists) { if (encoder->m_param->bRepeatHeaders) @@ -251,6 +260,9 @@ } encoder->printReconfigureParams(); } + /* Zones support modifying num of Refs. Requires determining level at each zone start*/ + if (encoder->m_param->rc.zonefileCount) + determineLevel(*encoder->m_latestParam, encoder->m_vps); return ret; } @@ -408,6 +420,7 @@ x265_analysis_inter_data *interData = analysis->interData = NULL; x265_analysis_intra_data *intraData = analysis->intraData = NULL; x265_analysis_distortion_data *distortionData = analysis->distortionData = NULL; + bool isVbv = param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0; int numDir = 2; //irrespective of P or B slices set direction as 2 uint32_t numPlanes = param->internalCsp == X265_CSP_I400 ? 1 : 3; @@ -419,18 +432,19 @@ #else uint32_t numCUs_sse_t = analysis->numCUsInFrame; #endif - - //Allocate memory for distortionData pointer - CHECKED_MALLOC_ZERO(distortionData, x265_analysis_distortion_data, 1); - CHECKED_MALLOC_ZERO(distortionData->distortion, sse_t, analysis->numPartitions * numCUs_sse_t); - if (param->rc.bStatRead) + if (param->analysisMultiPassRefine || param->analysisMultiPassDistortion || param->ctuDistortionRefine) { - CHECKED_MALLOC_ZERO(distortionData->ctuDistortion, sse_t, numCUs_sse_t); - CHECKED_MALLOC_ZERO(distortionData->scaledDistortion, double, analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(distortionData->offset, double, analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(distortionData->threshold, double, analysis->numCUsInFrame); + //Allocate memory for distortionData pointer + CHECKED_MALLOC_ZERO(distortionData, x265_analysis_distortion_data, 1); + CHECKED_MALLOC_ZERO(distortionData->ctuDistortion, sse_t, analysis->numPartitions * numCUs_sse_t); + if (param->analysisLoad || param->rc.bStatRead) + { + CHECKED_MALLOC_ZERO(distortionData->scaledDistortion, double, analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(distortionData->offset, double, analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(distortionData->threshold, double, analysis->numCUsInFrame); + } + analysis->distortionData = distortionData; } - analysis->distortionData = distortionData; if (param->bDisableLookahead && isVbv) { @@ -441,7 +455,7 @@ } //Allocate memory for weightParam pointer - if (!(param->bMVType == AVC_INFO)) + if (!(param->bAnalysisType == AVC_INFO)) CHECKED_MALLOC_ZERO(analysis->wt, x265_weight_param, numPlanes * numDir); if (param->analysisReuseLevel < 2) @@ -450,16 +464,20 @@ //Allocate memory for intraData pointer CHECKED_MALLOC_ZERO(intraData, x265_analysis_intra_data, 1); CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (param->rc.cuTree) + CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); analysis->intraData = intraData; //Allocate memory for interData pointer based on ReuseLevels CHECKED_MALLOC_ZERO(interData, x265_analysis_inter_data, 1); CHECKED_MALLOC(interData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (param->rc.cuTree) + CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[0], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[1], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mv[0], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame); @@ -467,16 +485,16 @@ if (param->analysisReuseLevel > 4) { - CHECKED_MALLOC(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mergeFlag, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } if (param->analysisReuseLevel >= 7) { - CHECKED_MALLOC(interData->interDir, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC(interData->sadCost, int64_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(interData->interDir, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(interData->sadCost, int64_t, analysis->numPartitions * analysis->numCUsInFrame); for (int dir = 0; dir < numDir; dir++) { - CHECKED_MALLOC(interData->refIdx[dir], int8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(interData->refIdx[dir], int8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(analysis->modeFlag[dir], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } } @@ -512,10 +530,9 @@ //Free memory for distortionData pointers if (analysis->distortionData) { - X265_FREE((analysis->distortionData)->distortion); - if (param->rc.bStatRead) + X265_FREE((analysis->distortionData)->ctuDistortion); + if (param->rc.bStatRead || param->analysisLoad) { - X265_FREE((analysis->distortionData)->ctuDistortion); X265_FREE((analysis->distortionData)->scaledDistortion); X265_FREE((analysis->distortionData)->offset); X265_FREE((analysis->distortionData)->threshold); @@ -524,7 +541,7 @@ } /* Early exit freeing weights alone if level is 1 (when there is no analysis inter/intra) */ - if (analysis->wt && !(param->bMVType == AVC_INFO)) + if (analysis->wt && !(param->bAnalysisType == AVC_INFO)) X265_FREE(analysis->wt); if (param->analysisReuseLevel < 2) @@ -537,6 +554,8 @@ X265_FREE((analysis->intraData)->modes); X265_FREE((analysis->intraData)->partSizes); X265_FREE((analysis->intraData)->chromaModes); + if (param->rc.cuTree) + X265_FREE((analysis->intraData)->cuQPOff); X265_FREE(analysis->intraData); analysis->intraData = NULL; } @@ -546,6 +565,8 @@ { X265_FREE((analysis->interData)->depth); X265_FREE((analysis->interData)->modes); + if (param->rc.cuTree) + X265_FREE((analysis->interData)->cuQPOff); X265_FREE((analysis->interData)->mvpIdx[0]); X265_FREE((analysis->interData)->mvpIdx[1]); X265_FREE((analysis->interData)->mv[0]); @@ -598,8 +619,10 @@ pic->quantOffsets = NULL; pic->userSEI.payloads = NULL; pic->userSEI.numPayloads = 0; + pic->rpu.payloadSize = 0; + pic->rpu.payload = NULL; - if ((param->analysisSave || param->analysisLoad) || (param->bMVType == AVC_INFO)) + if ((param->analysisSave || param->analysisLoad) || (param->bAnalysisType == AVC_INFO)) { uint32_t widthInCU = (param->sourceWidth + param->maxCUSize - 1) >> param->maxLog2CUSize; uint32_t heightInCU = (param->sourceHeight + param->maxCUSize - 1) >> param->maxLog2CUSize; @@ -612,6 +635,8 @@ void x265_picture_free(x265_picture *p) { + if (p->rpu.payload) + X265_FREE(p->rpu.payload); return x265_free(p); } @@ -661,9 +686,9 @@ #if ENABLE_LIBVMAF &x265_calculate_vmafscore, &x265_calculate_vmaf_framelevelscore, - &x265_vmaf_encoder_log + &x265_vmaf_encoder_log, #endif - + &PARAM_NS::x265_zone_param_parse }; typedef const x265_api* (*api_get_func)(int bitDepth); @@ -681,9 +706,11 @@ #include <dlfcn.h> #define ext ".so" #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif static int g_recursion /* = 0 */; - const x265_api* x265_api_get(int bitDepth) { if (bitDepth && bitDepth != X265_DEPTH) @@ -1483,11 +1510,11 @@ double x265_calculate_vmafscore(x265_param *param, x265_vmaf_data *data) { double score; - + data->width = param->sourceWidth; data->height = param->sourceHeight; data->internalBitDepth = param->internalBitDepth; - + if (param->internalCsp == X265_CSP_I420) { if ((param->sourceWidth * param->sourceHeight) % 2 != 0) @@ -1500,8 +1527,8 @@ data->offset = param->sourceWidth * param->sourceHeight * 2; else x265_log(NULL, X265_LOG_ERROR, "Invalid format\n"); - - compute_vmaf(&score, vcd->format, data->width, data->height, read_frame, data, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool); + + compute_vmaf(&score, vcd->format, data->width, data->height, read_frame, data, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool, vcd->thread, vcd->subsample, vcd->enable_conf_interval); return score; } @@ -1514,11 +1541,11 @@ PicYuv *distorted_frame = (PicYuv *)user_data->distorted_frame; if(!user_data->frame_set) { - + int reference_stride = reference_frame->m_stride; int distorted_stride = distorted_frame->m_stride; - const uint16_t *reference_ptr = (const uint16_t *)reference_frame->m_picOrg[0]; + const uint16_t *reference_ptr = (const uint16_t *)reference_frame->m_picOrg[0]; const uint16_t *distorted_ptr = (const uint16_t *)distorted_frame->m_picOrg[0]; temp_data = reference_data; @@ -1534,7 +1561,7 @@ reference_ptr += reference_stride; temp_data += stride / sizeof(*temp_data); } - + temp_data = distorted_data; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { @@ -1546,8 +1573,8 @@ user_data->frame_set = 1; return 0; - } - return 2; + } + return 2; } int read_frame_8bit(float *reference_data, float *distorted_data, float *temp_data, int stride, void *s) @@ -1578,7 +1605,7 @@ reference_ptr += reference_stride; temp_data += stride / sizeof(*temp_data); } - + temp_data = distorted_data; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { @@ -1590,8 +1617,8 @@ user_data->frame_set = 1; return 0; - } - return 2; + } + return 2; } double x265_calculate_vmaf_framelevelscore(x265_vmaf_framedata *vmafframedata) @@ -1603,8 +1630,8 @@ read_frame = read_frame_8bit; else read_frame = read_frame_10bit; - compute_vmaf(&score, vcd->format, vmafframedata->width, vmafframedata->height, read_frame, vmafframedata, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool); - + compute_vmaf(&score, vcd->format, vmafframedata->width, vmafframedata->height, read_frame, vmafframedata, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool, vcd->thread, vcd->subsample, vcd->enable_conf_interval); + return score; } #endif
View file
x265_2.9.tar.gz/source/encoder/dpb.h -> x265_3.0.tar.gz/source/encoder/dpb.h
Changed
@@ -52,6 +52,14 @@ m_lastIDR = 0; m_pocCRA = 0; m_bhasLeadingPicture = param->radl; + for (int i = 0; i < param->rc.zonefileCount; i++) + { + if (param->rc.zones[i].zoneParam->radl) + { + m_bhasLeadingPicture = param->rc.zones[i].zoneParam->radl; + break; + } + } m_bRefreshPending = false; m_frameDataFreeList = NULL; m_bOpenGOP = param->bOpenGOP;
View file
x265_2.9.tar.gz/source/encoder/encoder.cpp -> x265_3.0.tar.gz/source/encoder/encoder.cpp
Changed
@@ -3,6 +3,8 @@ * * Authors: Steve Borho <steve@borho.org> * Min Chen <chenm003@163.com> + * Praveen Kumar Tiwari <praveen@multicorewareinc.com> + * Aruna Matheswaran <aruna@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 @@ -46,6 +48,32 @@ namespace X265_NS { const char g_sliceTypeToChar[] = {'B', 'P', 'I'}; + +/* Dolby Vision profile specific settings */ +typedef struct +{ + int bEmitHRDSEI; + int bEnableVideoSignalTypePresentFlag; + int bEnableColorDescriptionPresentFlag; + int bEnableAccessUnitDelimiters; + int bAnnexB; + + /* VUI parameters specific to Dolby Vision Profile */ + int videoFormat; + int bEnableVideoFullRangeFlag; + int transferCharacteristics; + int colorPrimaries; + int matrixCoeffs; + + int doviProfileId; +}DolbyVisionProfileSpec; + +DolbyVisionProfileSpec dovi[] = +{ + { 1, 1, 1, 1, 1, 5, 1, 2, 2, 2, 50 }, + { 1, 1, 1, 1, 1, 5, 0, 16, 9, 9, 81 }, + { 1, 1, 1, 1, 1, 5, 0, 1, 1, 1, 82 } +}; } /* Threshold for motion vection, based on expermental result. @@ -411,7 +439,7 @@ m_nalList.m_annexB = !!m_param->bAnnexB; - m_emitCLLSEI = p->maxCLL || p->maxFALL; + m_emitCLLSEI = p->maxCLL || p->maxFALL || (p->dolbyProfile == 81); if (m_param->naluFile) { @@ -998,11 +1026,11 @@ } Frame *inFrame; + x265_param* p = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param; if (m_dpb->m_freeList.empty()) { inFrame = new Frame; inFrame->m_encodeStartTime = x265_mdate(); - x265_param* p = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param; if (inFrame->create(p, pic_in->quantOffsets)) { /* the first PicYuv created is asked to generate the CU and block unit offset @@ -1073,6 +1101,14 @@ copyUserSEIMessages(inFrame, pic_in); + /*Copy Dolby Vision RPU from pic_in to frame*/ + if (pic_in->rpu.payloadSize) + { + inFrame->m_rpu.payloadSize = pic_in->rpu.payloadSize; + inFrame->m_rpu.payload = new uint8_t[pic_in->rpu.payloadSize]; + memcpy(inFrame->m_rpu.payload, pic_in->rpu.payload, pic_in->rpu.payloadSize); + } + if (pic_in->quantOffsets != NULL) { int cuCount; @@ -1110,7 +1146,7 @@ { /* reads analysis data for the frame and allocates memory based on slicetype */ static int paramBytes = 0; - if (!inFrame->m_poc) + if (!inFrame->m_poc && m_param->bAnalysisType != HEVC_INFO) { x265_analysis_data analysisData = pic_in->analysisData; paramBytes = validateAnalysisData(&analysisData, 0); @@ -1218,7 +1254,7 @@ x265_frame_stats* frameData = NULL; /* Free up pic_in->analysisData since it has already been used */ - if ((m_param->analysisLoad && !m_param->analysisSave) || (m_param->bMVType && slice->m_sliceType != I_SLICE)) + if ((m_param->analysisLoad && !m_param->analysisSave) || ((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE)) x265_free_analysis_data(m_param, &outFrame->m_analysisData); if (pic_out) @@ -1256,9 +1292,9 @@ pic_out->analysisData.wt = outFrame->m_analysisData.wt; pic_out->analysisData.interData = outFrame->m_analysisData.interData; pic_out->analysisData.intraData = outFrame->m_analysisData.intraData; + pic_out->analysisData.distortionData = outFrame->m_analysisData.distortionData; pic_out->analysisData.modeFlag[0] = outFrame->m_analysisData.modeFlag[0]; pic_out->analysisData.modeFlag[1] = outFrame->m_analysisData.modeFlag[1]; - pic_out->analysisData.distortionData = outFrame->m_analysisData.distortionData; if (m_param->bDisableLookahead) { int factor = 1; @@ -1427,6 +1463,12 @@ readAnalysisFile(&frameEnc->m_analysisData, frameEnc->m_poc, frameEnc->m_lowres.sliceType); } + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + if (m_param->rc.zones[i].startFrame == frameEnc->m_poc) + x265_encoder_reconfig(this, m_param->rc.zones[i].zoneParam); + } + if (frameEnc->m_reconfigureRc && m_reconfigureRc) { memcpy(m_param, m_latestParam, sizeof(x265_param)); @@ -1631,6 +1673,27 @@ encParam->bIntraInBFrames = param->bIntraInBFrames; if (param->scalingLists && !encParam->scalingLists) encParam->scalingLists = strdup(param->scalingLists); + + encParam->rc.aqMode = param->rc.aqMode; + encParam->rc.aqStrength = param->rc.aqStrength; + encParam->noiseReductionInter = param->noiseReductionInter; + encParam->noiseReductionIntra = param->noiseReductionIntra; + + encParam->limitModes = param->limitModes; + encParam->bEnableSplitRdSkip = param->bEnableSplitRdSkip; + encParam->bCULossless = param->bCULossless; + encParam->bEnableRdRefine = param->bEnableRdRefine; + encParam->limitTU = param->limitTU; + encParam->bEnableTSkipFast = param->bEnableTSkipFast; + encParam->rdPenalty = param->rdPenalty; + encParam->dynamicRd = param->dynamicRd; + encParam->bEnableTransformSkip = param->bEnableTransformSkip; + encParam->bEnableAMP = param->bEnableAMP; + + /* Resignal changes in params in Parameter Sets */ + m_sps.maxAMPDepth = (m_sps.bUseAMP = param->bEnableAMP && param->bEnableAMP) ? param->maxCUDepth : 0; + m_pps.bTransformSkipEnabled = param->bEnableTransformSkip ? 1 : 0; + } encParam->forceFlush = param->forceFlush; /* To add: Loop Filter/deblocking controls, transform skip, signhide require PPS to be resent */ @@ -2360,6 +2423,13 @@ { sbacCoder.setBitstream(&bs); + if (m_param->dolbyProfile && !m_param->bRepeatHeaders) + { + bs.resetBits(); + bs.write(0x10, 8); + list.serialize(NAL_UNIT_ACCESS_UNIT_DELIMITER, bs); + } + /* headers for start of bitstream */ bs.resetBits(); sbacCoder.codeVPS(m_vps); @@ -2381,10 +2451,13 @@ if (m_param->bEmitHDRSEI) { - SEIContentLightLevel cllsei; - cllsei.max_content_light_level = m_param->maxCLL; - cllsei.max_pic_average_light_level = m_param->maxFALL; - cllsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal); + if (m_emitCLLSEI) + { + SEIContentLightLevel cllsei; + cllsei.max_content_light_level = m_param->maxCLL; + cllsei.max_pic_average_light_level = m_param->maxFALL; + cllsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal); + } if (m_param->masteringDisplayColorVolume) { @@ -2564,20 +2637,91 @@ pps->numRefIdxDefault[1] = 1; } +void Encoder::configureZone(x265_param *p, x265_param *zone) +{ + p->maxNumReferences = zone->maxNumReferences; + p->bEnableFastIntra = zone->bEnableFastIntra; + p->bEnableEarlySkip = zone->bEnableEarlySkip; + p->bEnableRecursionSkip = zone->bEnableRecursionSkip; + p->searchMethod = zone->searchMethod; + p->searchRange = zone->searchRange; + p->subpelRefine = zone->subpelRefine; + p->rdoqLevel = zone->rdoqLevel; + p->rdLevel = zone->rdLevel; + p->bEnableRectInter = zone->bEnableRectInter; + p->maxNumMergeCand = zone->maxNumMergeCand; + p->bIntraInBFrames = zone->bIntraInBFrames; + p->scalingLists = strdup(zone->scalingLists); + + p->rc.aqMode = zone->rc.aqMode; + p->rc.aqStrength = zone->rc.aqStrength; + p->noiseReductionInter = zone->noiseReductionInter; + p->noiseReductionIntra = zone->noiseReductionIntra; + + p->limitModes = zone->limitModes; + p->bEnableSplitRdSkip = zone->bEnableSplitRdSkip; + p->bCULossless = zone->bCULossless; + p->bEnableRdRefine = zone->bEnableRdRefine; + p->limitTU = zone->limitTU; + p->bEnableTSkipFast = zone->bEnableTSkipFast; + p->rdPenalty = zone->rdPenalty; + p->dynamicRd = zone->dynamicRd; + p->bEnableTransformSkip = zone->bEnableTransformSkip; + p->bEnableAMP = zone->bEnableAMP; + + if (m_param->rc.rateControlMode == X265_RC_ABR) + p->rc.bitrate = zone->rc.bitrate; + if (m_param->rc.rateControlMode == X265_RC_CRF) + p->rc.rfConstant = zone->rc.rfConstant; + if (m_param->rc.rateControlMode == X265_RC_CQP) + { + p->rc.qp = zone->rc.qp; + p->rc.aqMode = X265_AQ_NONE; + p->rc.hevcAq = 0; + } + p->radl = zone->radl; + memcpy(zone, p, sizeof(x265_param)); +} + +void Encoder::configureDolbyVisionParams(x265_param* p) +{ + uint32_t doviProfile = 0; + + while (dovi[doviProfile].doviProfileId != p->dolbyProfile && doviProfile + 1 < sizeof(dovi) / sizeof(dovi[0])) + doviProfile++; + + p->bEmitHRDSEI = dovi[doviProfile].bEmitHRDSEI; + p->vui.bEnableVideoSignalTypePresentFlag = dovi[doviProfile].bEnableVideoSignalTypePresentFlag; + p->vui.bEnableColorDescriptionPresentFlag = dovi[doviProfile].bEnableColorDescriptionPresentFlag; + p->bEnableAccessUnitDelimiters = dovi[doviProfile].bEnableAccessUnitDelimiters; + p->bAnnexB = dovi[doviProfile].bAnnexB; + p->vui.videoFormat = dovi[doviProfile].videoFormat; + p->vui.bEnableVideoFullRangeFlag = dovi[doviProfile].bEnableVideoFullRangeFlag; + p->vui.transferCharacteristics = dovi[doviProfile].transferCharacteristics; + p->vui.colorPrimaries = dovi[doviProfile].colorPrimaries; + p->vui.matrixCoeffs = dovi[doviProfile].matrixCoeffs; + + if (dovi[doviProfile].doviProfileId == 81) + p->bEmitHDRSEI = 1; + + if (dovi[doviProfile].doviProfileId == 50 && p->noiseReductionIntra && p->noiseReductionInter) + p->crQpOffset = 4; +} + void Encoder::configure(x265_param *p) { this->m_param = p; - if (p->bMVType == AVC_INFO) + if (p->bAnalysisType == AVC_INFO) this->m_externalFlush = true; else this->m_externalFlush = false; - if (p->bMVType == AVC_INFO && (p->limitTU == 3 || p->limitTU == 4)) + if (p->bAnalysisType == AVC_INFO && (p->limitTU == 3 || p->limitTU == 4)) { x265_log(p, X265_LOG_WARNING, "limit TU = 3 or 4 with MVType AVCINFO produces inconsistent output\n"); } - if (p->bMVType == AVC_INFO && p->minCUSize != 8) + if (p->bAnalysisType == AVC_INFO && p->minCUSize != 8) { p->minCUSize = 8; x265_log(p, X265_LOG_WARNING, "Setting minCuSize = 8, AVCINFO expects 8x8 blocks\n"); @@ -2667,6 +2811,7 @@ if (p->rc.rateControlMode == X265_RC_CQP) { p->rc.aqMode = X265_AQ_NONE; + p->rc.hevcAq = 0; p->rc.bitrate = 0; p->rc.cuTree = 0; p->rc.aqStrength = 0; @@ -2689,12 +2834,17 @@ x265_log(p, X265_LOG_WARNING, "Max TU size should be less than or equal to max CU size, setting max TU size = %d\n", p->maxCUSize); p->maxTUSize = p->maxCUSize; } - if (p->rc.aqStrength == 0 && p->rc.cuTree == 0) + { p->rc.aqMode = X265_AQ_NONE; - + p->rc.hevcAq = 0; + } if (p->rc.aqMode == X265_AQ_NONE && p->rc.cuTree == 0) p->rc.aqStrength = 0; + if (p->rc.hevcAq && p->rc.aqMode) + { + x265_log(p, X265_LOG_WARNING, "hevc-aq enabled, disabling other aq-modes\n"); + } if (p->totalFrames && p->totalFrames <= 2 * ((float)p->fpsNum) / p->fpsDenom && p->rc.bStrictCbr) p->lookaheadDepth = p->totalFrames; @@ -2736,16 +2886,16 @@ p->rc.rfConstantMin = 0; } - if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation)) + if (!(p->bAnalysisType == HEVC_INFO) && (p->analysisLoad || p->analysisSave) && p->rc.cuTree && p->analysisReuseLevel < 10) { - x265_log(p, X265_LOG_WARNING, "Analysis load/save options incompatible with pmode/pme, Disabling pmode/pme\n"); - p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0; + x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis reuse level 10, Disabling cu-tree\n"); + p->rc.cuTree = 0; } - if ((p->analysisLoad || p->analysisSave) && p->rc.cuTree) + if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation)) { - x265_log(p, X265_LOG_WARNING, "Analysis load/save options works only with cu-tree off, Disabling cu-tree\n"); - p->rc.cuTree = 0; + x265_log(p, X265_LOG_WARNING, "Analysis load/save options incompatible with pmode/pme, Disabling pmode/pme\n"); + p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0; } if ((p->analysisLoad || p->analysisSave) && (p->analysisMultiPassRefine || p->analysisMultiPassDistortion)) @@ -2805,7 +2955,7 @@ p->interRefine = 1; } - if (p->limitTU && (p->interRefine || p->bDynamicRefine)) + if (!(p->bAnalysisType == HEVC_INFO) && p->limitTU && (p->interRefine || p->bDynamicRefine)) { x265_log(p, X265_LOG_WARNING, "Inter refinement does not support limitTU. Disabling limitTU.\n"); p->limitTU = 0; @@ -2825,6 +2975,20 @@ } } + if (p->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) + { + if (!p->analysisLoad && !p->analysisSave) + { + x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 requires analysis save/load. Disabling refine-ctu-distortion\n"); + p->ctuDistortionRefine = 0; + } + if (p->scaleFactor && p->analysisLoad) + { + x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 cannot be enabled along with multi resolution analysis refinement. Disabling refine-ctu-distortion\n"); + p->ctuDistortionRefine = 0; + } + } + if ((p->analysisMultiPassRefine || p->analysisMultiPassDistortion) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation)) { x265_log(p, X265_LOG_WARNING, "multi-pass-opt-analysis/multi-pass-opt-distortion incompatible with pmode/pme, Disabling pmode/pme\n"); @@ -3180,6 +3344,20 @@ x265_log(p, X265_LOG_WARNING, "chunk-end cannot be less than chunk-start. Disabling chunking.\n"); } + if (p->dolbyProfile) // Default disabled. + configureDolbyVisionParams(p); + + if (m_param->rc.zonefileCount && p->bOpenGOP) + { + p->bOpenGOP = 0; + x265_log(p, X265_LOG_WARNING, "Zone encoding requires closed gop structure. Enabling closed GOP.\n"); + } + + if (m_param->rc.zonefileCount && !p->bRepeatHeaders) + { + p->bRepeatHeaders = 1; + x265_log(p, X265_LOG_WARNING, "Turning on repeat - headers for zone encoding\n"); + } } void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes) @@ -3205,6 +3383,7 @@ const x265_analysis_data *picData = &(picIn->analysisData); x265_analysis_intra_data *intraPic = picData->intraData; x265_analysis_inter_data *interPic = picData->interData; + x265_analysis_distortion_data *picDistortion = picData->distortionData; int poc; uint32_t frameRecordSize; X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize)); @@ -3240,6 +3419,7 @@ X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost)); X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame)); X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions)); + if (m_param->bDisableLookahead) { X265_FREAD(&analysis->numCuInHeight, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->numCuInHeight)); @@ -3252,6 +3432,12 @@ analysis->numPartitions *= factor; /* Memory is allocated for inter and intra analysis data based on the slicetype */ x265_alloc_analysis_data(m_param, analysis); + + if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) + { + X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileIn, picDistortion); + computeDistortionOffset(analysis); + } if (m_param->bDisableLookahead && m_rateControl->m_isVbv) { size_t vbvCount = m_param->lookaheadDepth + m_param->bframes + 2; @@ -3280,19 +3466,25 @@ } if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) { + if (m_param->bAnalysisType == HEVC_INFO) + return; if (m_param->analysisReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; + int8_t *cuQPBuf = NULL; tempBuf = X265_MALLOC(uint8_t, depthBytes * 3); depthBuf = tempBuf; modeBuf = tempBuf + depthBytes; partSizes = tempBuf + 2 * depthBytes; + if (m_param->rc.cuTree) + cuQPBuf = X265_MALLOC(int8_t, depthBytes); X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth); X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes); X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes); + if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); } size_t count = 0; for (uint32_t d = 0; d < depthBytes; d++) @@ -3308,6 +3500,8 @@ memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes); memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes); memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes); + if (m_param->rc.cuTree) + memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes); count += bytes; } @@ -3323,6 +3517,8 @@ memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor); X265_FREE(tempLumaBuf); } + if (m_param->rc.cuTree) + X265_FREE(cuQPBuf); X265_FREE(tempBuf); consumedBytes += frameRecordSize; } @@ -3339,6 +3535,7 @@ uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2]; MV* mv[2]; int8_t* refIdx[2]; + int8_t* cuQPBuf = NULL; int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; @@ -3348,91 +3545,107 @@ bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames); if (bIntraInInter) numBuf++; } - - tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf); - depthBuf = tempBuf; - modeBuf = tempBuf + depthBytes; - - X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth); - X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); - - if (m_param->analysisReuseLevel > 4) + if (m_param->bAnalysisType == HEVC_INFO) { - partSize = modeBuf + depthBytes; - mergeFlag = partSize + depthBytes; - X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); - X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); + depthBytes = analysis->numCUsInFrame * analysis->numPartitions; + memcpy(((x265_analysis_inter_data *)analysis->interData)->depth, interPic->depth, depthBytes); + } + else + { + tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf); + depthBuf = tempBuf; + modeBuf = tempBuf + depthBytes; + if (m_param->rc.cuTree) + cuQPBuf = X265_MALLOC(int8_t, depthBytes); + + X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth); + X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); + if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisReuseLevel > 4) { - interDir = mergeFlag + depthBytes; - X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); - if (bIntraInInter) - { - chromaDir = interDir + depthBytes; - X265_FREAD(chromaDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes); - } - for (uint32_t i = 0; i < numDir; i++) - { - mvpIdx[i] = X265_MALLOC(uint8_t, depthBytes); - refIdx[i] = X265_MALLOC(int8_t, depthBytes); - mv[i] = X265_MALLOC(MV, depthBytes); - X265_FREAD(mvpIdx[i], sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mvpIdx[i]); - X265_FREAD(refIdx[i], sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->refIdx[i]); - X265_FREAD(mv[i], sizeof(MV), depthBytes, m_analysisFileIn, interPic->mv[i]); + partSize = modeBuf + depthBytes; + mergeFlag = partSize + depthBytes; + X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); + X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); + + if (m_param->analysisReuseLevel == 10) + { + interDir = mergeFlag + depthBytes; + X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); + if (bIntraInInter) + { + chromaDir = interDir + depthBytes; + X265_FREAD(chromaDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes); + } + for (uint32_t i = 0; i < numDir; i++) + { + mvpIdx[i] = X265_MALLOC(uint8_t, depthBytes); + refIdx[i] = X265_MALLOC(int8_t, depthBytes); + mv[i] = X265_MALLOC(MV, depthBytes); + X265_FREAD(mvpIdx[i], sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mvpIdx[i]); + X265_FREAD(refIdx[i], sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->refIdx[i]); + X265_FREAD(mv[i], sizeof(MV), depthBytes, m_analysisFileIn, interPic->mv[i]); + } } } - } - size_t count = 0; - for (uint32_t d = 0; d < depthBytes; d++) - { - int bytes = analysis->numPartitions >> (depthBuf[d] * 2); - if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && depthBuf[d] == 0) - depthBuf[d] = 1; - memset(&(analysis->interData)->depth[count], depthBuf[d], bytes); - memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); - if (m_param->analysisReuseLevel > 4) + size_t count = 0; + for (uint32_t d = 0; d < depthBytes; d++) { - if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN) - partSize[d] = SIZE_2Nx2N; - memset(&(analysis->interData)->partSize[count], partSize[d], bytes); - int numPU = (modeBuf[d] == MODE_INTRA) ? 1 : nbPartsTable[(int)partSize[d]]; - for (int pu = 0; pu < numPU; pu++) - { - if (pu) d++; - (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; - if (m_param->analysisReuseLevel == 10) + int bytes = analysis->numPartitions >> (depthBuf[d] * 2); + if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && depthBuf[d] == 0) + depthBuf[d] = 1; + memset(&(analysis->interData)->depth[count], depthBuf[d], bytes); + memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); + if (m_param->rc.cuTree) + memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); + if (m_param->analysisReuseLevel > 4) + { + if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN) + partSize[d] = SIZE_2Nx2N; + memset(&(analysis->interData)->partSize[count], partSize[d], bytes); + int numPU = (modeBuf[d] == MODE_INTRA) ? 1 : nbPartsTable[(int)partSize[d]]; + for (int pu = 0; pu < numPU; pu++) { - (analysis->interData)->interDir[count + pu] = interDir[d]; - for (uint32_t i = 0; i < numDir; i++) + if (pu) d++; + (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; + if (m_param->analysisReuseLevel == 10) { - (analysis->interData)->mvpIdx[i][count + pu] = mvpIdx[i][d]; - (analysis->interData)->refIdx[i][count + pu] = refIdx[i][d]; - if (m_param->scaleFactor) + (analysis->interData)->interDir[count + pu] = interDir[d]; + for (uint32_t i = 0; i < numDir; i++) { - mv[i][d].x *= (int16_t)m_param->scaleFactor; - mv[i][d].y *= (int16_t)m_param->scaleFactor; + (analysis->interData)->mvpIdx[i][count + pu] = mvpIdx[i][d]; + (analysis->interData)->refIdx[i][count + pu] = refIdx[i][d]; + if (m_param->scaleFactor) + { + mv[i][d].x *= (int16_t)m_param->scaleFactor; + mv[i][d].y *= (int16_t)m_param->scaleFactor; + } + memcpy(&(analysis->interData)->mv[i][count + pu], &mv[i][d], sizeof(MV)); } - memcpy(&(analysis->interData)->mv[i][count + pu], &mv[i][d], sizeof(MV)); } } + if (m_param->analysisReuseLevel == 10 && bIntraInInter) + memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) - memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); + count += bytes; } - count += bytes; - } - - X265_FREE(tempBuf); + if (m_param->rc.cuTree) + X265_FREE(cuQPBuf); + X265_FREE(tempBuf); + } if (m_param->analysisReuseLevel == 10) { - for (uint32_t i = 0; i < numDir; i++) + if (m_param->bAnalysisType != HEVC_INFO) { - X265_FREE(mvpIdx[i]); - X265_FREE(refIdx[i]); - X265_FREE(mv[i]); + for (uint32_t i = 0; i < numDir; i++) + { + X265_FREE(mvpIdx[i]); + X265_FREE(refIdx[i]); + X265_FREE(mv[i]); + } } if (bIntraInInter) { @@ -3484,6 +3697,7 @@ const x265_analysis_data *picData = &(picIn->analysisData); x265_analysis_intra_data *intraPic = picData->intraData; x265_analysis_inter_data *interPic = picData->interData; + x265_analysis_distortion_data *picDistortion = picData->distortionData; int poc; uint32_t frameRecordSize; X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->frameRecordSize)); @@ -3519,6 +3733,7 @@ X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost)); X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame)); X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions)); + if (m_param->bDisableLookahead) { X265_FREAD(&analysis->numCuInHeight, sizeof(uint32_t), 1, m_analysisFileIn, &(picData->numCuInHeight)); @@ -3538,6 +3753,12 @@ /* Memory is allocated for inter and intra analysis data based on the slicetype */ x265_alloc_analysis_data(m_param, analysis); + if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) + { + X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileIn, picDistortion); + computeDistortionOffset(analysis); + } + analysis->numPartitions = numPartitions * factor; analysis->numCUsInFrame = numCUsInFrame; analysis->numCuInHeight = numCuInHeight; @@ -3602,15 +3823,19 @@ return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; + int8_t *cuQPBuf = NULL; tempBuf = X265_MALLOC(uint8_t, depthBytes * 3); depthBuf = tempBuf; modeBuf = tempBuf + depthBytes; partSizes = tempBuf + 2 * depthBytes; + if (m_param->rc.cuTree) + cuQPBuf = X265_MALLOC(int8_t, depthBytes); X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth); X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes); X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes); + if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); } uint32_t count = 0; for (uint32_t d = 0; d < depthBytes; d++) @@ -3632,6 +3857,8 @@ memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes); memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes); memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes); + if (m_param->rc.cuTree) + memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes); count += bytes; d += getCUIndex(&cuLoc, &count, bytes, 1); } @@ -3650,6 +3877,8 @@ ctu32Idx += getCUIndex(&cuLoc, &cnt, factor, 0); } X265_FREE(tempLumaBuf); + if (m_param->rc.cuTree) + X265_FREE(cuQPBuf); X265_FREE(tempBuf); consumedBytes += frameRecordSize; } @@ -3666,6 +3895,7 @@ uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2]; MV* mv[2]; int8_t* refIdx[2]; + int8_t* cuQPBuf = NULL; int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; @@ -3679,9 +3909,12 @@ tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf); depthBuf = tempBuf; modeBuf = tempBuf + depthBytes; + if (m_param->rc.cuTree) + cuQPBuf = X265_MALLOC(int8_t, depthBytes); X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth); X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); + if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } if (m_param->analysisReuseLevel > 4) { partSize = modeBuf + depthBytes; @@ -3730,6 +3963,8 @@ { memset(&(analysis->interData)->depth[count], writeDepth, bytes); memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); + if (m_param->rc.cuTree) + memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); if (m_param->analysisReuseLevel == 10 && bIntraInInter) memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); @@ -3790,6 +4025,8 @@ } } + if (m_param->rc.cuTree) + X265_FREE(cuQPBuf); X265_FREE(tempBuf); if (m_param->analysisReuseLevel == 10) @@ -3891,6 +4128,8 @@ X265_PARAM_VALIDATE(saveParam->lookaheadDepth, sizeof(int), 1, &m_param->lookaheadDepth, rc - lookahead); X265_PARAM_VALIDATE(saveParam->chunkStart, sizeof(int), 1, &m_param->chunkStart, chunk-start); X265_PARAM_VALIDATE(saveParam->chunkEnd, sizeof(int), 1, &m_param->chunkEnd, chunk-end); + X265_PARAM_VALIDATE(saveParam->cuTree,sizeof(int),1,&m_param->rc.cuTree, cutree - offset); + X265_PARAM_VALIDATE(saveParam->ctuDistortionRefine, sizeof(int), 1, &m_param->ctuDistortionRefine, ctu - distortion); int sourceHeight, sourceWidth; if (writeFlag) @@ -4042,7 +4281,31 @@ } return SIZE_2Nx2N; } +void Encoder::computeDistortionOffset(x265_analysis_data* analysis) +{ + x265_analysis_distortion_data *distortionData = analysis->distortionData; + double sum = 0.0, sqrSum = 0.0; + for (uint32_t i = 0; i < analysis->numCUsInFrame; ++i) + { + distortionData->scaledDistortion[i] = X265_LOG2(X265_MAX(distortionData->ctuDistortion[i], 1)); + sum += distortionData->scaledDistortion[i]; + sqrSum += distortionData->scaledDistortion[i] * distortionData->scaledDistortion[i]; + } + double avg = sum / analysis->numCUsInFrame; + distortionData->sdDistortion = pow(((sqrSum / analysis->numCUsInFrame) - (avg * avg)), 0.5); + distortionData->averageDistortion = avg; + distortionData->highDistortionCtuCount = distortionData->lowDistortionCtuCount = 0; + for (uint32_t i = 0; i < analysis->numCUsInFrame; ++i) + { + distortionData->threshold[i] = distortionData->scaledDistortion[i] / distortionData->averageDistortion; + distortionData->offset[i] = (distortionData->averageDistortion - distortionData->scaledDistortion[i]) / distortionData->sdDistortion; + if (distortionData->threshold[i] < 0.9 && distortionData->offset[i] >= 1) + distortionData->lowDistortionCtuCount++; + else if (distortionData->threshold[i] > 1.1 && distortionData->offset[i] <= -1) + distortionData->highDistortionCtuCount++; + } +} void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, int sliceType) { @@ -4070,21 +4333,16 @@ /* Now arrived at the right frame, read the record */ analysis->frameRecordSize = frameRecordSize; uint8_t* tempBuf = NULL, *depthBuf = NULL; - sse_t *tempdistBuf = NULL, *distortionBuf = NULL; + X265_FREAD((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileIn); tempBuf = X265_MALLOC(uint8_t, depthBytes); X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn); - tempdistBuf = X265_MALLOC(sse_t, depthBytes); - X265_FREAD(tempdistBuf, sizeof(sse_t), depthBytes, m_analysisFileIn); depthBuf = tempBuf; - distortionBuf = tempdistBuf; x265_analysis_data *analysisData = (x265_analysis_data*)analysis; x265_analysis_intra_data *intraData = analysisData->intraData; x265_analysis_inter_data *interData = analysisData->interData; - x265_analysis_distortion_data *distortionData = analysisData->distortionData; + computeDistortionOffset(analysis); size_t count = 0; - uint32_t ctuCount = 0; - double sum = 0, sqrSum = 0; for (uint32_t d = 0; d < depthBytes; d++) { int bytes = analysis->numPartitions >> (depthBuf[d] * 2); @@ -4092,30 +4350,10 @@ memset(&intraData->depth[count], depthBuf[d], bytes); else memset(&interData->depth[count], depthBuf[d], bytes); - distortionData->distortion[count] = distortionBuf[d]; - distortionData->ctuDistortion[ctuCount] += distortionData->distortion[count]; count += bytes; - if ((count % (unsigned)analysis->numPartitions) == 0) - { - distortionData->scaledDistortion[ctuCount] = X265_LOG2(X265_MAX(distortionData->ctuDistortion[ctuCount], 1)); - sum += distortionData->scaledDistortion[ctuCount]; - sqrSum += distortionData->scaledDistortion[ctuCount] * distortionData->scaledDistortion[ctuCount]; - ctuCount++; - } - } - double avg = sum / analysis->numCUsInFrame; - distortionData->sdDistortion = pow(((sqrSum / analysis->numCUsInFrame) - (avg * avg)), 0.5); - distortionData->averageDistortion = avg; - distortionData->highDistortionCtuCount = distortionData->lowDistortionCtuCount = 0; - for (uint32_t i = 0; i < analysis->numCUsInFrame; ++i) - { - distortionData->threshold[i] = distortionData->scaledDistortion[i] / distortionData->averageDistortion; - distortionData->offset[i] = (distortionData->averageDistortion - distortionData->scaledDistortion[i]) / distortionData->sdDistortion; - if (distortionData->threshold[i] < 0.9 && distortionData->offset[i] >= 1) - distortionData->lowDistortionCtuCount++; - else if (distortionData->threshold[i] > 1.1 && distortionData->offset[i] <= -1) - distortionData->highDistortionCtuCount++; } + + if (!IS_X265_TYPE_I(sliceType)) { MV *tempMVBuf[2], *MVBuf[2]; @@ -4168,11 +4406,27 @@ X265_FREE(tempModeBuf); } X265_FREE(tempBuf); - X265_FREE(tempdistBuf); #undef X265_FREAD } +void Encoder::copyDistortionData(x265_analysis_data* analysis, FrameData &curEncData) +{ + for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++) + { + uint8_t depth = 0; + CUData* ctu = curEncData.getPicCTU(cuAddr); + x265_analysis_distortion_data *distortionData = (x265_analysis_distortion_data *)analysis->distortionData; + distortionData->ctuDistortion[cuAddr] = 0; + for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions;) + { + depth = ctu->m_cuDepth[absPartIdx]; + distortionData->ctuDistortion[cuAddr] += ctu->m_distortion[absPartIdx]; + absPartIdx += ctu->m_numPartitions >> (depth * 2); + } + } +} + void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncData) { @@ -4208,8 +4462,15 @@ analysis->frameRecordSize += sizeof(WeightParam) * numPlanes * numDir; } + if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) + { + copyDistortionData(analysis, curEncData); + analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t); + } + if (m_param->analysisReuseLevel > 1) { + if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) { for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++) @@ -4220,6 +4481,7 @@ CUData* ctu = curEncData.getPicCTU(cuAddr); x265_analysis_intra_data* intraDataCTU = analysis->intraData; + int baseQP = (int)(ctu->m_encData->m_cuStat[cuAddr].baseQp + 0.5); for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++) { @@ -4232,6 +4494,8 @@ partSize = ctu->m_partSize[absPartIdx]; intraDataCTU->partSizes[depthBytes] = partSize; + if (m_param->rc.cuTree) + intraDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP); absPartIdx += ctu->m_numPartitions >> (depth * 2); } memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions); @@ -4249,6 +4513,7 @@ CUData* ctu = curEncData.getPicCTU(cuAddr); x265_analysis_inter_data* interDataCTU = analysis->interData; x265_analysis_intra_data* intraDataCTU = analysis->intraData; + int baseQP = (int)(ctu->m_encData->m_cuStat[cuAddr].baseQp + 0.5); for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++) { @@ -4257,9 +4522,11 @@ predMode = ctu->m_predMode[absPartIdx]; if (m_param->analysisReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1) - predMode = 4; // used as indiacator if the block is coded as bidir + predMode = 4; // used as indicator if the block is coded as bidir interDataCTU->modes[depthBytes] = predMode; + if (m_param->rc.cuTree) + interDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP); if (m_param->analysisReuseLevel > 4) { @@ -4295,12 +4562,16 @@ } } - if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) + if ((analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) && m_param->rc.cuTree) + analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3 + (sizeof(int8_t) * depthBytes); + else if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3; else { - /* Add sizeof depth, modes, partSize, mergeFlag */ + /* Add sizeof depth, modes, partSize, cuQPOffset, mergeFlag */ analysis->frameRecordSize += depthBytes * 2; + if (m_param->rc.cuTree) + analysis->frameRecordSize += (sizeof(int8_t) * depthBytes); if (m_param->analysisReuseLevel > 4) analysis->frameRecordSize += (depthBytes * 2); @@ -4331,6 +4602,8 @@ X265_FWRITE(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileOut); X265_FWRITE(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileOut); X265_FWRITE(&analysis->numPartitions, sizeof(int), 1, m_analysisFileOut); + if (m_param->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) + X265_FWRITE((analysis->distortionData)->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileOut); if (analysis->sliceType > X265_TYPE_I) X265_FWRITE((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileOut); @@ -4342,12 +4615,16 @@ X265_FWRITE((analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->intraData)->partSizes, sizeof(char), depthBytes, m_analysisFileOut); + if (m_param->rc.cuTree) + X265_FWRITE((analysis->intraData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut); } else { X265_FWRITE((analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut); + if (m_param->rc.cuTree) + X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut); if (m_param->analysisReuseLevel > 4) { X265_FWRITE((analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFileOut); @@ -4390,25 +4667,24 @@ x265_analysis_inter_data *interData = analysisData->interData; x265_analysis_distortion_data *distortionData = analysisData->distortionData; - for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++) - { - uint8_t depth = 0; - - CUData* ctu = curEncData.getPicCTU(cuAddr); + copyDistortionData(analysis, curEncData); - for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++) + if (curEncData.m_slice->m_sliceType == I_SLICE) + { + for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++) { - depth = ctu->m_cuDepth[absPartIdx]; - if (curEncData.m_slice->m_sliceType == I_SLICE) + uint8_t depth = 0; + CUData* ctu = curEncData.getPicCTU(cuAddr); + for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++) + { + depth = ctu->m_cuDepth[absPartIdx]; intraData->depth[depthBytes] = depth; - else - interData->depth[depthBytes] = depth; - distortionData->distortion[depthBytes] = ctu->m_distortion[absPartIdx]; - absPartIdx += ctu->m_numPartitions >> (depth * 2); + absPartIdx += ctu->m_numPartitions >> (depth * 2); + } } } - if (curEncData.m_slice->m_sliceType != I_SLICE) + else { int32_t* ref[2]; ref[0] = (analysis->interData)->ref; @@ -4423,6 +4699,7 @@ for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++) { depth = ctu->m_cuDepth[absPartIdx]; + interData->depth[depthBytes] = depth; interData->mv[0][depthBytes].word = ctu->m_mv[0][absPartIdx].word; interData->mvpIdx[0][depthBytes] = ctu->m_mvpIdx[0][absPartIdx]; ref[0][depthBytes] = ctu->m_refIdx[0][absPartIdx]; @@ -4444,7 +4721,7 @@ /* calculate frameRecordSize */ analysis->frameRecordSize = sizeof(analysis->frameRecordSize) + sizeof(depthBytes) + sizeof(analysis->poc); analysis->frameRecordSize += depthBytes * sizeof(uint8_t); - analysis->frameRecordSize += depthBytes * sizeof(sse_t); + analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t); if (curEncData.m_slice->m_sliceType != I_SLICE) { int numDir = (curEncData.m_slice->m_sliceType == P_SLICE) ? 1 : 2; @@ -4456,6 +4733,7 @@ X265_FWRITE(&analysis->frameRecordSize, sizeof(uint32_t), 1, m_analysisFileOut); X265_FWRITE(&depthBytes, sizeof(uint32_t), 1, m_analysisFileOut); X265_FWRITE(&analysis->poc, sizeof(uint32_t), 1, m_analysisFileOut); + X265_FWRITE(distortionData->ctuDistortion, sizeof(sse_t), analysis->numCUsInFrame, m_analysisFileOut); if (curEncData.m_slice->m_sliceType == I_SLICE) { X265_FWRITE((analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut); @@ -4464,7 +4742,6 @@ { X265_FWRITE((analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut); } - X265_FWRITE(distortionData->distortion, sizeof(sse_t), depthBytes, m_analysisFileOut); if (curEncData.m_slice->m_sliceType != I_SLICE) { int numDir = curEncData.m_slice->m_sliceType == P_SLICE ? 1 : 2;
View file
x265_2.9.tar.gz/source/encoder/encoder.h -> x265_3.0.tar.gz/source/encoder/encoder.h
Changed
@@ -193,6 +193,9 @@ bool m_aborted; // fatal error detected bool m_reconfigure; // Encoder reconfigure in progress bool m_reconfigureRc; + bool m_reconfigureZone; + + int m_saveCtuDistortionLevel; /* Begin intra refresh when one not in progress or else begin one as soon as the current * one is done. Requires bIntraRefresh to be set.*/ @@ -273,6 +276,8 @@ void configure(x265_param *param); + void configureZone(x265_param *p, x265_param *zone); + void updateVbvPlan(RateControl* rc); void readAnalysisFile(x265_analysis_data* analysis, int poc, int sliceType); @@ -281,6 +286,8 @@ void readAnalysisFile(x265_analysis_data* analysis, int poc, const x265_picture* picIn, int paramBytes, cuLocation cuLoc); + void computeDistortionOffset(x265_analysis_data* analysis); + int getCUIndex(cuLocation* cuLoc, uint32_t* count, int bytes, int flag); int getPuShape(puOrientation* puOrient, int partSize, int numCTU); @@ -289,6 +296,8 @@ void writeAnalysisFileRefine(x265_analysis_data* analysis, FrameData &curEncData); + void copyDistortionData(x265_analysis_data* analysis, FrameData &curEncData); + void finishFrameStats(Frame* pic, FrameEncoder *curEncoder, x265_frame_stats* frameStats, int inPoc); int validateAnalysisData(x265_analysis_data* analysis, int readWriteFlag); @@ -304,6 +313,8 @@ void copyUserSEIMessages(Frame *frame, const x265_picture* pic_in); + void configureDolbyVisionParams(x265_param* p); + protected: void initVPS(VPS *vps);
View file
x265_2.9.tar.gz/source/encoder/frameencoder.cpp -> x265_3.0.tar.gz/source/encoder/frameencoder.cpp
Changed
@@ -335,7 +335,7 @@ while (!m_frame->m_ctuInfo) m_frame->m_copied.wait(); } - if ((m_param->bMVType == AVC_INFO) && !m_param->analysisSave && !m_param->analysisLoad && !(IS_X265_TYPE_I(m_frame->m_lowres.sliceType))) + if ((m_param->bAnalysisType == AVC_INFO) && !m_param->analysisSave && !m_param->analysisLoad && !(IS_X265_TYPE_I(m_frame->m_lowres.sliceType))) { while (((m_frame->m_analysisData.interData == NULL && m_frame->m_analysisData.intraData == NULL) || (uint32_t)m_frame->m_poc != m_frame->m_analysisData.poc)) m_frame->m_copyMVType.wait(); @@ -657,6 +657,8 @@ bpSei->m_auCpbRemovalDelayDelta = 1; bpSei->m_cpbDelayOffset = 0; bpSei->m_dpbDelayOffset = 0; + bpSei->m_concatenationFlag = (m_param->bEnableHRDConcatFlag && !m_frame->m_poc) ? true : false; + // hrdFullness() calculates the initial CPB removal delay and offset m_top->m_rateControl->hrdFullness(bpSei); bpSei->writeSEImessages(m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList, m_param->bSingleSeiNal); @@ -1063,6 +1065,14 @@ m_accessUnitBits = bytes << 3; } + if (m_frame->m_rpu.payloadSize) + { + m_bs.resetBits(); + for (int i = 0; i < m_frame->m_rpu.payloadSize; i++) + m_bs.write(m_frame->m_rpu.payload[i], 8); + m_nalList.serialize(NAL_UNIT_UNSPECIFIED, m_bs); + } + m_endCompressTime = x265_mdate(); /* Decrement referenced frame reference counts, allow them to be recycled */ @@ -1599,11 +1609,11 @@ if (!m_param->bEnableWavefront && col == numCols - 1) { double qpBase = curEncData.m_cuStat[cuAddr].baseQp; - int reEncode = m_top->m_rateControl->rowVbvRateControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId); + curRow.reEncode = m_top->m_rateControl->rowVbvRateControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId); qpBase = x265_clip3((double)m_param->rc.qpMin, (double)m_param->rc.qpMax, qpBase); curEncData.m_rowStat[row].rowQp = qpBase; curEncData.m_rowStat[row].rowQpScale = x265_qp2qScale(qpBase); - if (reEncode < 0) + if (curRow.reEncode < 0) { x265_log(m_param, X265_LOG_DEBUG, "POC %d row %d - encode restart required for VBV, to %.2f from %.2f\n", m_frame->m_poc, row, qpBase, curEncData.m_cuStat[cuAddr].baseQp); @@ -1642,17 +1652,19 @@ curEncData.m_rowStat[r].sumQpRc += curEncData.m_cuStat[c].baseQp; curEncData.m_rowStat[r].numEncodedCUs = c; } + if (curRow.reEncode < 0) + break; startCuAddr = EndCuAddr - numCols; EndCuAddr = startCuAddr + 1; } } double qpBase = curEncData.m_cuStat[cuAddr].baseQp; - int reEncode = m_top->m_rateControl->rowVbvRateControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId); + curRow.reEncode = m_top->m_rateControl->rowVbvRateControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId); qpBase = x265_clip3((double)m_param->rc.qpMin, (double)m_param->rc.qpMax, qpBase); curEncData.m_rowStat[row].rowQp = qpBase; curEncData.m_rowStat[row].rowQpScale = x265_qp2qScale(qpBase); - if (reEncode < 0) + if (curRow.reEncode < 0) { x265_log(m_param, X265_LOG_DEBUG, "POC %d row %d - encode restart required for VBV, to %.2f from %.2f\n", m_frame->m_poc, row, qpBase, curEncData.m_cuStat[cuAddr].baseQp);
View file
x265_2.9.tar.gz/source/encoder/frameencoder.h -> x265_3.0.tar.gz/source/encoder/frameencoder.h
Changed
@@ -97,6 +97,8 @@ volatile uint32_t completed; volatile uint32_t avgQPComputed; + volatile int reEncode; + /* called at the start of each frame to initialize state */ void init(Entropy& initContext, unsigned int sid) { @@ -105,6 +107,7 @@ completed = 0; avgQPComputed = 0; sliceId = sid; + reEncode = 0; memset(&rowStats, 0, sizeof(rowStats)); rowGoOnCoder.load(initContext); }
View file
x265_2.9.tar.gz/source/encoder/nal.cpp -> x265_3.0.tar.gz/source/encoder/nal.cpp
Changed
@@ -97,7 +97,7 @@ /* Will write size later */ bytes += 4; } - else if (!m_numNal || nalUnitType == NAL_UNIT_VPS || nalUnitType == NAL_UNIT_SPS || nalUnitType == NAL_UNIT_PPS) + else if (!m_numNal || nalUnitType == NAL_UNIT_VPS || nalUnitType == NAL_UNIT_SPS || nalUnitType == NAL_UNIT_PPS || nalUnitType == NAL_UNIT_UNSPECIFIED) { memcpy(out, startCodePrefix, 4); bytes += 4; @@ -124,7 +124,7 @@ * - 0x000002 */ for (uint32_t i = 0; i < payloadSize; i++) { - if (i > 2 && !out[bytes - 2] && !out[bytes - 3] && out[bytes - 1] <= 0x03) + if (i > 2 && !out[bytes - 2] && !out[bytes - 3] && out[bytes - 1] <= 0x03 && nalUnitType != NAL_UNIT_UNSPECIFIED) { /* inject 0x03 to prevent emulating a start code */ out[bytes] = out[bytes - 1];
View file
x265_2.9.tar.gz/source/encoder/ratecontrol.cpp -> x265_3.0.tar.gz/source/encoder/ratecontrol.cpp
Changed
@@ -153,10 +153,7 @@ int lowresCuHeight = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; m_ncu = lowresCuWidth * lowresCuHeight; - if (m_param->rc.cuTree) - m_qCompress = 1; - else - m_qCompress = m_param->rc.qCompress; + m_qCompress = (m_param->rc.cuTree && !m_param->rc.hevcAq) ? 1 : m_param->rc.qCompress; // validate for param->rc, maybe it is need to add a function like x265_parameters_valiate() m_residualFrames = 0; @@ -381,13 +378,14 @@ m_isGrainEnabled = false; if(m_param->rc.bEnableGrain) // tune for grainy content OR equal p-b frame sizes - m_isGrainEnabled = true; + m_isGrainEnabled = true; for (int i = 0; i < 3; i++) - m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN); + m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN); m_avgPFrameQp = 0 ; /* 720p videos seem to be a good cutoff for cplxrSum */ - double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 : m_isGrainEnabled ? 1.9 : 1; + double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree && !m_param->rc.hevcAq) ? 2.5 : m_param->rc.hevcAq ? 1.5 : m_isGrainEnabled ? 1.9 : 1.0; + /* estimated ratio that produces a reasonable QP for the first I-frame */ m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) * tuneCplxFactor; m_wantedBitsWindow = m_bitrate * m_frameDuration; @@ -741,6 +739,20 @@ if (m_param->rc.rfConstantMin) m_rateFactorMaxDecrement = m_param->rc.rfConstant - m_param->rc.rfConstantMin; } + if (m_param->rc.rateControlMode == X265_RC_CQP) + { + m_qp = m_param->rc.qp; + if (m_qp && !m_param->bLossless) + { + m_qpConstant[P_SLICE] = m_qp; + m_qpConstant[I_SLICE] = x265_clip3(QP_MIN, QP_MAX_MAX, (int)(m_qp - m_ipOffset + 0.5)); + m_qpConstant[B_SLICE] = x265_clip3(QP_MIN, QP_MAX_MAX, (int)(m_qp + m_pbOffset + 0.5)); + } + else + { + m_qpConstant[P_SLICE] = m_qpConstant[I_SLICE] = m_qpConstant[B_SLICE] = m_qp; + } + } m_bitrate = m_param->rc.bitrate * 1000; } @@ -1231,6 +1243,17 @@ rce->keptAsRef = IS_REFERENCED(curFrame); m_predType = getPredictorType(curFrame->m_lowres.sliceType, m_sliceType); rce->poc = m_curSlice->m_poc; + + /* change ratecontrol stats for next zone if specified */ + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + if (m_param->rc.zones[i].startFrame == curFrame->m_encodeOrder) + { + m_param = m_param->rc.zones[i].zoneParam; + reconfigureRC(); + init(*m_curSlice->m_sps); + } + } if (m_param->rc.bStatRead) { X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n"); @@ -2538,7 +2561,7 @@ { double q; - if (m_param->rc.cuTree) + if (m_param->rc.cuTree && !m_param->rc.hevcAq) { // Scale and units are obtained from rateNum and rateDenom for videos with fixed frame rates. double timescale = (double)m_param->fpsDenom / (2 * m_param->fpsNum); @@ -2546,6 +2569,7 @@ } else q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress); + // avoid NaN's in the Rceq if (rce->coeffBits + rce->mvBits == 0) q = m_lastQScaleFor[rce->sliceType];
View file
x265_2.9.tar.gz/source/encoder/search.cpp -> x265_3.0.tar.gz/source/encoder/search.cpp
Changed
@@ -2201,7 +2201,7 @@ cu.getNeighbourMV(puIdx, pu.puAbsPartIdx, interMode.interNeighbours); /* Uni-directional prediction */ if ((m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) - || (m_param->analysisMultiPassRefine && m_param->rc.bStatRead) || (m_param->bMVType == AVC_INFO) || (useAsMVP)) + || (m_param->analysisMultiPassRefine && m_param->rc.bStatRead) || (m_param->bAnalysisType == AVC_INFO) || (useAsMVP)) { for (int list = 0; list < numPredDir; list++) {
View file
x265_2.9.tar.gz/source/encoder/sei.cpp -> x265_3.0.tar.gz/source/encoder/sei.cpp
Changed
@@ -66,7 +66,8 @@ if (!isNested) { - bs.writeByteAlignment(); + if (nalUnitType != NAL_UNIT_UNSPECIFIED) + bs.writeByteAlignment(); list.serialize(nalUnitType, bs); } }
View file
x265_2.9.tar.gz/source/encoder/sei.h -> x265_3.0.tar.gz/source/encoder/sei.h
Changed
@@ -220,6 +220,7 @@ SEIBufferingPeriod() : m_cpbDelayOffset(0) , m_dpbDelayOffset(0) + , m_concatenationFlag(0) , m_auCpbRemovalDelayDelta(1) { m_payloadType = BUFFERING_PERIOD; @@ -227,6 +228,7 @@ } bool m_cpbDelayOffset; bool m_dpbDelayOffset; + bool m_concatenationFlag; uint32_t m_initialCpbRemovalDelay; uint32_t m_initialCpbRemovalDelayOffset; uint32_t m_auCpbRemovalDelayDelta; @@ -237,7 +239,7 @@ WRITE_UVLC(0, "bp_seq_parameter_set_id"); WRITE_FLAG(0, "rap_cpb_params_present_flag"); - WRITE_FLAG(0, "concatenation_flag"); + WRITE_FLAG(m_concatenationFlag, "concatenation_flag"); WRITE_CODE(m_auCpbRemovalDelayDelta - 1, hrd.cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1"); WRITE_CODE(m_initialCpbRemovalDelay, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay"); WRITE_CODE(m_initialCpbRemovalDelayOffset, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset");
View file
x265_2.9.tar.gz/source/encoder/slicetype.cpp -> x265_3.0.tar.gz/source/encoder/slicetype.cpp
Changed
@@ -3,6 +3,7 @@ * * Authors: Gopu Govindaswamy <gopu@multicorewareinc.com> * Steve Borho <steve@borho.org> + * Ashok Kumar Mishra <ashok@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 @@ -105,6 +106,7 @@ x265_emms(); return var; } + /* Find the sum of pixels of each block for luma plane */ uint32_t LookaheadTLD::lumaSumCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, uint32_t qgSize) { @@ -121,6 +123,157 @@ return (uint32_t)sum_ssd; } +void LookaheadTLD::xPreanalyzeQp(Frame* curFrame) +{ + const uint32_t width = curFrame->m_fencPic->m_picWidth; + const uint32_t height = curFrame->m_fencPic->m_picHeight; + + for (uint32_t d = 0; d < 4; d++) + { + int ctuSizeIdx = 6 - g_log2Size[curFrame->m_param->maxCUSize]; + int aqDepth = g_log2Size[curFrame->m_param->maxCUSize] - g_log2Size[curFrame->m_param->rc.qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + PicQPAdaptationLayer* pcAQLayer = &curFrame->m_lowres.pAQLayer[d]; + const uint32_t aqPartWidth = pcAQLayer->aqPartWidth; + const uint32_t aqPartHeight = pcAQLayer->aqPartHeight; + double* pcAQU = pcAQLayer->dActivity; + double* pcQP = pcAQLayer->dQpOffset; + double* pcCuTree = pcAQLayer->dCuTreeOffset; + + for (uint32_t y = 0; y < height; y += aqPartHeight) + { + for (uint32_t x = 0; x < width; x += aqPartWidth, pcAQU++, pcQP++, pcCuTree++) + { + double dMaxQScale = pow(2.0, curFrame->m_param->rc.qpAdaptationRange / 6.0); + double dCUAct = *pcAQU; + double dAvgAct = pcAQLayer->dAvgActivity; + + double dNormAct = (dMaxQScale*dCUAct + dAvgAct) / (dCUAct + dMaxQScale*dAvgAct); + double dQpOffset = (X265_LOG2(dNormAct) / X265_LOG2(2.0)) * 6.0; + *pcQP = dQpOffset; + *pcCuTree = dQpOffset; + } + } + } +} + +void LookaheadTLD::xPreanalyze(Frame* curFrame) +{ + const uint32_t width = curFrame->m_fencPic->m_picWidth; + const uint32_t height = curFrame->m_fencPic->m_picHeight; + const intptr_t stride = curFrame->m_fencPic->m_stride; + + for (uint32_t d = 0; d < 4; d++) + { + int ctuSizeIdx = 6 - g_log2Size[curFrame->m_param->maxCUSize]; + int aqDepth = g_log2Size[curFrame->m_param->maxCUSize] - g_log2Size[curFrame->m_param->rc.qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + const pixel* src = curFrame->m_fencPic->m_picOrg[0];; + PicQPAdaptationLayer* pQPLayer = &curFrame->m_lowres.pAQLayer[d]; + const uint32_t aqPartWidth = pQPLayer->aqPartWidth; + const uint32_t aqPartHeight = pQPLayer->aqPartHeight; + double* pcAQU = pQPLayer->dActivity; + + double dSumAct = 0.0; + for (uint32_t y = 0; y < height; y += aqPartHeight) + { + const uint32_t currAQPartHeight = X265_MIN(aqPartHeight, height - y); + for (uint32_t x = 0; x < width; x += aqPartWidth, pcAQU++) + { + const uint32_t currAQPartWidth = X265_MIN(aqPartWidth, width - x); + const pixel* pBlkY = &src[x]; + uint64_t sum[4] = { 0, 0, 0, 0 }; + uint64_t sumSq[4] = { 0, 0, 0, 0 }; + uint32_t by = 0; + for (; by < currAQPartHeight >> 1; by++) + { + uint32_t bx = 0; + for (; bx < currAQPartWidth >> 1; bx++) + { + sum[0] += pBlkY[bx]; + sumSq[0] += pBlkY[bx] * pBlkY[bx]; + } + for (; bx < currAQPartWidth; bx++) + { + sum[1] += pBlkY[bx]; + sumSq[1] += pBlkY[bx] * pBlkY[bx]; + } + pBlkY += stride; + } + for (; by < currAQPartHeight; by++) + { + uint32_t bx = 0; + for (; bx < currAQPartWidth >> 1; bx++) + { + sum[2] += pBlkY[bx]; + sumSq[2] += pBlkY[bx] * pBlkY[bx]; + } + for (; bx < currAQPartWidth; bx++) + { + sum[3] += pBlkY[bx]; + sumSq[3] += pBlkY[bx] * pBlkY[bx]; + } + pBlkY += stride; + } + + assert((currAQPartWidth & 1) == 0); + assert((currAQPartHeight & 1) == 0); + const uint32_t pixelWidthOfQuadrants = currAQPartWidth >> 1; + const uint32_t pixelHeightOfQuadrants = currAQPartHeight >> 1; + const uint32_t numPixInAQPart = pixelWidthOfQuadrants * pixelHeightOfQuadrants; + + double dMinVar = MAX_DOUBLE; + if (numPixInAQPart != 0) + { + for (int i = 0; i < 4; i++) + { + const double dAverage = double(sum[i]) / numPixInAQPart; + const double dVariance = double(sumSq[i]) / numPixInAQPart - dAverage * dAverage; + dMinVar = X265_MIN(dMinVar, dVariance); + } + } + else + { + dMinVar = 0.0; + } + double dActivity = 1.0 + dMinVar; + *pcAQU = dActivity; + dSumAct += dActivity; + } + src += stride * currAQPartHeight; + } + + const double dAvgAct = dSumAct / (pQPLayer->numAQPartInWidth * pQPLayer->numAQPartInHeight); + pQPLayer->dAvgActivity = dAvgAct; + } + + xPreanalyzeQp(curFrame); + + int minAQDepth = curFrame->m_lowres.pAQLayer->minAQDepth; + + PicQPAdaptationLayer* pQPLayer = &curFrame->m_lowres.pAQLayer[minAQDepth]; + const uint32_t aqPartWidth = pQPLayer->aqPartWidth; + const uint32_t aqPartHeight = pQPLayer->aqPartHeight; + double* pcQP = pQPLayer->dQpOffset; + + // Use new qp offset values for qpAqOffset, qpCuTreeOffset and invQscaleFactor buffer + int blockXY = 0; + for (uint32_t y = 0; y < height; y += aqPartHeight) + { + for (uint32_t x = 0; x < width; x += aqPartWidth, pcQP++) + { + curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(*pcQP); + blockXY++; + + acEnergyCu(curFrame, x, y, curFrame->m_param->internalCsp, curFrame->m_param->rc.qgSize); + } + } +} + void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param) { /* Actual adaptive quantization */ @@ -176,90 +329,99 @@ if (param->bEnableWeightedPred || param->bEnableWeightedBiPred) { for (int blockY = 0; blockY < maxRow; blockY += loopIncr) - for (int blockX = 0; blockX < maxCol; blockX += loopIncr) - acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); } } else { - int blockXY = 0; - double avg_adj_pow2 = 0.f, avg_adj = 0.f, qp_adj = 0.f; - double bias_strength = 0.f, strength = 0.f; - if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) + if (param->rc.hevcAq) { - double bit_depth_correction = 1.f / (1 << (2*(X265_DEPTH-8))); - - for (int blockY = 0; blockY < maxRow; blockY += loopIncr) - { - for (int blockX = 0; blockX < maxCol; blockX += loopIncr) - { - uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); - qp_adj = pow(energy * bit_depth_correction + 1, 0.1); - curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; - avg_adj += qp_adj; - avg_adj_pow2 += qp_adj * qp_adj; - blockXY++; - } - } - avg_adj /= blockCount; - avg_adj_pow2 /= blockCount; - strength = param->rc.aqStrength * avg_adj; - avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj; - bias_strength = param->rc.aqStrength; + // New method for calculating variance and qp offset + xPreanalyze(curFrame); } else - strength = param->rc.aqStrength * 1.0397f; - - blockXY = 0; - for (int blockY = 0; blockY < maxRow; blockY += loopIncr) { - for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + int blockXY = 0; + double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0; + double bias_strength = 0.f; + double strength = 0.f; + if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) { - if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) - { - qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; - qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj)); - } - else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE) - { - qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; - qp_adj = strength * (qp_adj - avg_adj); - } - else + double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8))); + + for (int blockY = 0; blockY < maxRow; blockY += loopIncr) { - uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp,param->rc.qgSize); - qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8))); + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + { + uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); + qp_adj = pow(energy * bit_depth_correction + 1, 0.1); + curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; + avg_adj += qp_adj; + avg_adj_pow2 += qp_adj * qp_adj; + blockXY++; + } } + avg_adj /= blockCount; + avg_adj_pow2 /= blockCount; + strength = param->rc.aqStrength * avg_adj; + avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj; + bias_strength = param->rc.aqStrength; + } + else + strength = param->rc.aqStrength * 1.0397f; - if (param->bHDROpt) + blockXY = 0; + for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + { + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) { - uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize); - uint32_t lumaAvg = sum / (loopIncr * loopIncr); - if (lumaAvg < 301) - qp_adj += 3; - else if (lumaAvg >= 301 && lumaAvg < 367) - qp_adj += 2; - else if (lumaAvg >= 367 && lumaAvg < 434) - qp_adj += 1; - else if (lumaAvg >= 501 && lumaAvg < 567) - qp_adj -= 1; - else if (lumaAvg >= 567 && lumaAvg < 634) - qp_adj -= 2; - else if (lumaAvg >= 634 && lumaAvg < 701) - qp_adj -= 3; - else if (lumaAvg >= 701 && lumaAvg < 767) - qp_adj -= 4; - else if (lumaAvg >= 767 && lumaAvg < 834) - qp_adj -= 5; - else if (lumaAvg >= 834) - qp_adj -= 6; - } - if (quantOffsets != NULL) - qp_adj += quantOffsets[blockXY]; - curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj; - curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; - curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj); - blockXY++; + if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) + { + qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; + qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj)); + } + else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE) + { + qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; + qp_adj = strength * (qp_adj - avg_adj); + } + else + { + uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); + qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8))); + } + + if (param->bHDROpt) + { + uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize); + uint32_t lumaAvg = sum / (loopIncr * loopIncr); + if (lumaAvg < 301) + qp_adj += 3; + else if (lumaAvg >= 301 && lumaAvg < 367) + qp_adj += 2; + else if (lumaAvg >= 367 && lumaAvg < 434) + qp_adj += 1; + else if (lumaAvg >= 501 && lumaAvg < 567) + qp_adj -= 1; + else if (lumaAvg >= 567 && lumaAvg < 634) + qp_adj -= 2; + else if (lumaAvg >= 634 && lumaAvg < 701) + qp_adj -= 3; + else if (lumaAvg >= 701 && lumaAvg < 767) + qp_adj -= 4; + else if (lumaAvg >= 767 && lumaAvg < 834) + qp_adj -= 5; + else if (lumaAvg >= 834) + qp_adj -= 6; + } + if (quantOffsets != NULL) + qp_adj += quantOffsets[blockXY]; + curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj; + curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; + curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj); + blockXY++; + } } } } @@ -301,11 +463,13 @@ { int blockXY = 0; for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + { for (int blockX = 0; blockX < maxCol; blockX += loopIncr) { curFrame->m_lowres.blockVariance[blockXY] = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); blockXY++; } + } } } @@ -596,13 +760,16 @@ /* Allow the strength to be adjusted via qcompress, since the two concepts * are very similar. */ - - m_cuTreeStrength = 5.0 * (1.0 - m_param->rc.qCompress); + m_cuTreeStrength = (m_param->rc.hevcAq ? 6.0 : 5.0) * (1.0 - m_param->rc.qCompress); m_lastKeyframe = -m_param->keyframeMax; m_sliceTypeBusy = false; m_fullQueueSize = X265_MAX(1, m_param->lookaheadDepth); - m_bAdaptiveQuant = m_param->rc.aqMode || m_param->bEnableWeightedPred || m_param->bEnableWeightedBiPred || m_param->bAQMotion; + m_bAdaptiveQuant = m_param->rc.aqMode || + m_param->bEnableWeightedPred || + m_param->bEnableWeightedBiPred || + m_param->bAQMotion || + m_param->rc.hevcAq; /* If we have a thread pool and are using --b-adapt 2, it is generally * preferable to perform all motion searches for each lowres frame in large @@ -919,10 +1086,11 @@ if (!m_param->analysisLoad || !m_param->bDisableLookahead) { X265_CHECK(curFrame->m_lowres.costEst[b - p0][p1 - b] > 0, "Slice cost not estimated\n") + if (m_param->rc.cuTree && !m_param->rc.bStatRead) /* update row satds based on cutree offsets */ curFrame->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1, b); - else if (!m_param->analysisLoad || m_param->scaleFactor) + else if (!m_param->analysisLoad || m_param->scaleFactor || m_param->bAnalysisType == HEVC_INFO) { if (m_param->rc.aqMode) curFrame->m_lowres.satdCost = curFrame->m_lowres.costEstAq[b - p0][p1 - b]; @@ -1077,7 +1245,7 @@ } int bframes, brefs; - if (!m_param->analysisLoad) + if (!m_param->analysisLoad || m_param->bAnalysisType == HEVC_INFO) { for (bframes = 0, brefs = 0;; bframes++) { @@ -1115,6 +1283,13 @@ frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR; } } + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + int curZoneStart = m_param->rc.zones[i].startFrame; + curZoneStart += curZoneStart ? m_param->rc.zones[i].zoneParam->radl : 0; + if (curZoneStart == frm.frameNum) + frm.sliceType = X265_TYPE_IDR; + } if ((frm.sliceType == X265_TYPE_I && frm.frameNum - m_lastKeyframe >= m_param->keyframeMin) || (frm.frameNum == (m_param->chunkStart - 1)) || (frm.frameNum == m_param->chunkEnd)) { if (m_param->bOpenGOP) @@ -1130,7 +1305,20 @@ /* Closed GOP */ m_lastKeyframe = frm.frameNum; frm.bKeyframe = true; - if (bframes > 0 && !m_param->radl) + int zoneRadl = 0; + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + int zoneStart = m_param->rc.zones[i].startFrame; + zoneStart += zoneStart ? m_param->rc.zones[i].zoneParam->radl : 0; + if (zoneStart == frm.frameNum) + { + zoneRadl = m_param->rc.zones[i].zoneParam->radl; + m_param->radl = 0; + m_param->rc.zones->zoneParam->radl = i < m_param->rc.zonefileCount - 1? m_param->rc.zones[i + 1].zoneParam->radl : 0; + break; + } + } + if (bframes > 0 && !m_param->radl && !zoneRadl) { list[bframes - 1]->m_lowres.sliceType = X265_TYPE_P; bframes--; @@ -1418,6 +1606,14 @@ } frames[framecnt + 1] = NULL; + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + int curZoneStart = m_param->rc.zones[i].startFrame, nextZoneStart = 0; + curZoneStart += curZoneStart ? m_param->rc.zones[i].zoneParam->radl : 0; + nextZoneStart += (i + 1 < m_param->rc.zonefileCount) ? m_param->rc.zones[i + 1].startFrame + m_param->rc.zones[i + 1].zoneParam->radl : m_param->totalFrames; + if (curZoneStart <= frames[0]->frameNum && nextZoneStart > frames[0]->frameNum) + m_param->keyframeMax = nextZoneStart - curZoneStart; + } int keylimit = m_param->keyframeMax; if (frames[0]->frameNum < m_param->chunkEnd) { @@ -1627,14 +1823,16 @@ frames[numFrames]->sliceType = X265_TYPE_P; } - bool bForceRADL = m_param->radl && !m_param->bOpenGOP; + int zoneRadl = m_param->rc.zonefileCount ? m_param->rc.zones->zoneParam->radl : 0; + bool bForceRADL = (m_param->radl || zoneRadl) && !m_param->bOpenGOP; bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false : true; - int preRADL = m_lastKeyframe + m_param->keyframeMax - m_param->radl - 1; /*Frame preceeding RADL in POC order*/ + int radl = m_param->radl ? m_param->radl : zoneRadl; + int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1; /*Frame preceeding RADL in POC order*/ if (bForceRADL && (frames[0]->frameNum == preRADL) && !bLastMiniGop) { int j = 1; - numBFrames = m_param->radl; - for (; j <= m_param->radl; j++) + numBFrames = m_param->radl ? m_param->radl : zoneRadl; + for (; j <= numBFrames; j++) frames[j]->sliceType = X265_TYPE_B; frames[j]->sliceType = X265_TYPE_I; } @@ -1665,6 +1863,7 @@ if (m_param->rc.cuTree) cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe); + if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1) && !m_extendGopBoundary) keyintLimit = keyFrameLimit; @@ -1898,6 +2097,7 @@ return cost; } + void Lookahead::aqMotion(Lowres **frames, bool bIntra) { if (!bIntra) @@ -2193,44 +2393,191 @@ cuTreeFinish(frames[b], averageDuration, b == p1 ? b - p0 : 0); } -void Lookahead::cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance) +void Lookahead::computeCUTreeQpOffset(Lowres *frame, double averageDuration, int ref0Distance) { int fpsFactor = (int)(CLIP_DURATION(averageDuration) / CLIP_DURATION((double)m_param->fpsDenom / m_param->fpsNum) * 256); - double weightdelta = 0.0; + uint32_t loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16; + double weightdelta = 0.0; if (ref0Distance && frame->weightedCostDelta[ref0Distance - 1] > 0) weightdelta = (1.0 - frame->weightedCostDelta[ref0Distance - 1]); + uint32_t widthFullRes = frame->widthFullRes; + uint32_t heightFullRes = frame->heightFullRes; + if (m_param->rc.qgSize == 8) { + int minAQDepth = frame->pAQLayer->minAQDepth; + + PicQPAdaptationLayer* pQPLayerMin = &frame->pAQLayer[minAQDepth]; + double* pcCuTree8x8 = pQPLayerMin->dCuTreeOffset8x8; + for (int cuY = 0; cuY < m_8x8Height; cuY++) { for (int cuX = 0; cuX < m_8x8Width; cuX++) { const int cuXY = cuX + cuY * m_8x8Width; - int intracost = ((frame->intraCost[cuXY]) / 4 * frame->invQscaleFactor8x8[cuXY] + 128) >> 8; + int intracost = ((frame->intraCost[cuXY] / 4) * frame->invQscaleFactor8x8[cuXY] + 128) >> 8; if (intracost) { - int propagateCost = ((frame->propagateCost[cuXY]) / 4 * fpsFactor + 128) >> 8; + int propagateCost = ((frame->propagateCost[cuXY] / 4) * fpsFactor + 128) >> 8; double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta; - frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4] - m_cuTreeStrength * (log2_ratio); - frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] - m_cuTreeStrength * (log2_ratio); - frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] - m_cuTreeStrength * (log2_ratio); - frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] - m_cuTreeStrength * (log2_ratio); + + pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4] = log2_ratio; + pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + 1] = log2_ratio; + pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = log2_ratio; + pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = log2_ratio; + } + } + } + + for (uint32_t d = 0; d < 4; d++) + { + int ctuSizeIdx = 6 - g_log2Size[m_param->maxCUSize]; + int aqDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + PicQPAdaptationLayer* pQPLayer = &frame->pAQLayer[d]; + const uint32_t aqPartWidth = pQPLayer->aqPartWidth; + const uint32_t aqPartHeight = pQPLayer->aqPartHeight; + + const uint32_t numAQPartInWidth = pQPLayer->numAQPartInWidth; + const uint32_t numAQPartInHeight = pQPLayer->numAQPartInHeight; + + double* pcQP = pQPLayer->dQpOffset; + double* pcCuTree = pQPLayer->dCuTreeOffset; + + uint32_t maxCols = frame->maxBlocksInRowFullRes; + + for (uint32_t y = 0; y < numAQPartInHeight; y++) + { + for (uint32_t x = 0; x < numAQPartInWidth; x++, pcQP++, pcCuTree++) + { + uint32_t block_x = x * aqPartWidth; + uint32_t block_y = y * aqPartHeight; + + uint32_t blockXY = 0; + double log2_ratio = 0; + for (uint32_t block_yy = block_y; block_yy < block_y + aqPartHeight && block_yy < heightFullRes; block_yy += loopIncr) + { + for (uint32_t block_xx = block_x; block_xx < block_x + aqPartWidth && block_xx < widthFullRes; block_xx += loopIncr) + { + uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr); + + log2_ratio += *(pcCuTree8x8 + idx); + + blockXY++; + } + } + + double qp_offset = (m_cuTreeStrength * log2_ratio) / blockXY; + + *pcCuTree = *pcQP - qp_offset; } } } } else { - for (int cuIndex = 0; cuIndex < m_cuCount; cuIndex++) + for (uint32_t d = 0; d < 4; d++) { - int intracost = (frame->intraCost[cuIndex] * frame->invQscaleFactor[cuIndex] + 128) >> 8; - if (intracost) + int ctuSizeIdx = 6 - g_log2Size[m_param->maxCUSize]; + int aqDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize]; + if (!aqLayerDepth[ctuSizeIdx][aqDepth][d]) + continue; + + PicQPAdaptationLayer* pQPLayer = &frame->pAQLayer[d]; + const uint32_t aqPartWidth = pQPLayer->aqPartWidth; + const uint32_t aqPartHeight = pQPLayer->aqPartHeight; + + const uint32_t numAQPartInWidth = pQPLayer->numAQPartInWidth; + const uint32_t numAQPartInHeight = pQPLayer->numAQPartInHeight; + + double* pcQP = pQPLayer->dQpOffset; + double* pcCuTree = pQPLayer->dCuTreeOffset; + + uint32_t maxCols = frame->maxBlocksInRow; + + for (uint32_t y = 0; y < numAQPartInHeight; y++) { - int propagateCost = (frame->propagateCost[cuIndex] * fpsFactor + 128) >> 8; - double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta; - frame->qpCuTreeOffset[cuIndex] = frame->qpAqOffset[cuIndex] - m_cuTreeStrength * log2_ratio; + for (uint32_t x = 0; x < numAQPartInWidth; x++, pcQP++, pcCuTree++) + { + uint32_t block_x = x * aqPartWidth; + uint32_t block_y = y * aqPartHeight; + + uint32_t blockXY = 0; + double log2_ratio = 0; + for (uint32_t block_yy = block_y; block_yy < block_y + aqPartHeight && block_yy < heightFullRes; block_yy += loopIncr) + { + for (uint32_t block_xx = block_x; block_xx < block_x + aqPartWidth && block_xx < widthFullRes; block_xx += loopIncr) + { + uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr); + + int intraCost = (frame->intraCost[idx] * frame->invQscaleFactor[idx] + 128) >> 8; + int propagateCost = (frame->propagateCost[idx] * fpsFactor + 128) >> 8; + + log2_ratio += (X265_LOG2(intraCost + propagateCost) - X265_LOG2(intraCost) + weightdelta); + + blockXY++; + } + } + + double qp_offset = (m_cuTreeStrength * log2_ratio) / blockXY; + + *pcCuTree = *pcQP - qp_offset; + + } + } + } + } +} + +void Lookahead::cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance) +{ + if (m_param->rc.hevcAq) + { + computeCUTreeQpOffset(frame, averageDuration, ref0Distance); + } + else + { + int fpsFactor = (int)(CLIP_DURATION(averageDuration) / CLIP_DURATION((double)m_param->fpsDenom / m_param->fpsNum) * 256); + double weightdelta = 0.0; + + if (ref0Distance && frame->weightedCostDelta[ref0Distance - 1] > 0) + weightdelta = (1.0 - frame->weightedCostDelta[ref0Distance - 1]); + + if (m_param->rc.qgSize == 8) + { + for (int cuY = 0; cuY < m_8x8Height; cuY++) + { + for (int cuX = 0; cuX < m_8x8Width; cuX++) + { + const int cuXY = cuX + cuY * m_8x8Width; + int intracost = ((frame->intraCost[cuXY]) / 4 * frame->invQscaleFactor8x8[cuXY] + 128) >> 8; + if (intracost) + { + int propagateCost = ((frame->propagateCost[cuXY]) / 4 * fpsFactor + 128) >> 8; + double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta; + frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4] - m_cuTreeStrength * (log2_ratio); + frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] - m_cuTreeStrength * (log2_ratio); + frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] - m_cuTreeStrength * (log2_ratio); + frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] - m_cuTreeStrength * (log2_ratio); + } + } + } + } + else + { + for (int cuIndex = 0; cuIndex < m_cuCount; cuIndex++) + { + int intracost = (frame->intraCost[cuIndex] * frame->invQscaleFactor[cuIndex] + 128) >> 8; + if (intracost) + { + int propagateCost = (frame->propagateCost[cuIndex] * fpsFactor + 128) >> 8; + double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta; + frame->qpCuTreeOffset[cuIndex] = frame->qpAqOffset[cuIndex] - m_cuTreeStrength * log2_ratio; + } } } } @@ -2245,31 +2592,71 @@ int64_t score = 0; int *rowSatd = frames[b]->rowSatds[b - p0][p1 - b]; - double *qp_offset = frames[b]->qpCuTreeOffset; x265_emms(); - for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--) + + if (m_param->rc.hevcAq) + { + int minAQDepth = frames[b]->pAQLayer->minAQDepth; + PicQPAdaptationLayer* pQPLayer = &frames[b]->pAQLayer[minAQDepth]; + double* pcQPCuTree = pQPLayer->dCuTreeOffset; + + // Use new qp offset values for qpAqOffset, qpCuTreeOffset and invQscaleFactor buffer + for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--) + { + rowSatd[cuy] = 0; + for (int cux = m_8x8Width - 1; cux >= 0; cux--) + { + int cuxy = cux + cuy * m_8x8Width; + int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK; + double qp_adj; + + if (m_param->rc.qgSize == 8) + qp_adj = (pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4] + + pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + 1] + + pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] + + pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4; + else + qp_adj = *(pcQPCuTree + cuxy); + + cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8; + rowSatd[cuy] += cuCost; + if ((cuy > 0 && cuy < m_8x8Height - 1 && + cux > 0 && cux < m_8x8Width - 1) || + m_8x8Width <= 2 || m_8x8Height <= 2) + { + score += cuCost; + } + } + } + } + else { - rowSatd[cuy] = 0; - for (int cux = m_8x8Width - 1; cux >= 0; cux--) + double *qp_offset = frames[b]->qpCuTreeOffset; + + for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--) { - int cuxy = cux + cuy * m_8x8Width; - int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK; - double qp_adj; - if (m_param->rc.qgSize == 8) - qp_adj = (qp_offset[cux * 2 + cuy * m_8x8Width * 4] + - qp_offset[cux * 2 + cuy * m_8x8Width * 4 + 1] + - qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] + - qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4; - else - qp_adj = qp_offset[cuxy]; - cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8; - rowSatd[cuy] += cuCost; - if ((cuy > 0 && cuy < m_8x8Height - 1 && - cux > 0 && cux < m_8x8Width - 1) || - m_8x8Width <= 2 || m_8x8Height <= 2) + rowSatd[cuy] = 0; + for (int cux = m_8x8Width - 1; cux >= 0; cux--) { - score += cuCost; + int cuxy = cux + cuy * m_8x8Width; + int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK; + double qp_adj; + if (m_param->rc.qgSize == 8) + qp_adj = (qp_offset[cux * 2 + cuy * m_8x8Width * 4] + + qp_offset[cux * 2 + cuy * m_8x8Width * 4 + 1] + + qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] + + qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4; + else + qp_adj = qp_offset[cuxy]; + cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8; + rowSatd[cuy] += cuCost; + if ((cuy > 0 && cuy < m_8x8Height - 1 && + cux > 0 && cux < m_8x8Width - 1) || + m_8x8Width <= 2 || m_8x8Height <= 2) + { + score += cuCost; + } } } }
View file
x265_2.9.tar.gz/source/encoder/slicetype.h -> x265_3.0.tar.gz/source/encoder/slicetype.h
Changed
@@ -87,7 +87,8 @@ void lowresIntraEstimate(Lowres& fenc, uint32_t qgSize); void weightsAnalyse(Lowres& fenc, Lowres& ref); - + void xPreanalyze(Frame* curFrame); + void xPreanalyzeQp(Frame* curFrame); protected: uint32_t acEnergyCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, int csp, uint32_t qgSize); @@ -175,6 +176,7 @@ void cuTree(Lowres **frames, int numframes, bool bintra); void estimateCUPropagate(Lowres **frames, double average_duration, int p0, int p1, int b, int referenced); void cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance); + void computeCUTreeQpOffset(Lowres *frame, double averageDuration, int ref0Distance); /* called by getEstimatedPictureCost() to finalize cuTree costs */ int64_t frameCostRecalculate(Lowres **frames, int p0, int p1, int b);
View file
x265_2.9.tar.gz/source/test/regression-tests.txt -> x265_3.0.tar.gz/source/test/regression-tests.txt
Changed
@@ -46,6 +46,7 @@ CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --tskip --tskip-fast --no-scenecut --limit-tu 1 CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --aq-mode 3 --aq-strength 1.5 --aq-motion --bitrate 5000 CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --aq-mode 3 --aq-strength 1.5 --no-psy-rd --ssim-rd +CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --hevc-aq --no-cutree --qg-size 16 DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset superfast --weightp --qg-size 16 DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset medium --tune psnr --bframes 16 --limit-modes DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset slow --temporal-layers --no-psy-rd --qg-size 32 --limit-refs 0 --cu-lossless @@ -172,6 +173,8 @@ crowd_run_1080p50.y4m,--preset medium --no-cutree --analysis-save x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 5000 --vbv-maxrate 5000 --vbv-bufsize 5000 --early-skip --tu-inter-depth 3::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-maxrate 10000 --vbv-bufsize 10000 --early-skip --tu-inter-depth 3 --refine-intra 4 --dynamic-refine::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-maxrate 10000 --vbv-bufsize 10000 --early-skip --tu-inter-depth 3 --refine-intra 3 --refine-inter 3 RaceHorses_416x240_30.y4m,--preset slow --no-cutree --ctu 16 --analysis-save x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --crf 22 --vbv-maxrate 1000 --vbv-bufsize 1000::RaceHorses_832x480_30.y4m, --preset slow --no-cutree --ctu 32 --analysis-load x265_analysis.dat --analysis-save x265_analysis_2.dat --analysis-reuse-level 10 --scale-factor 2 --crf 16 --vbv-maxrate 4000 --vbv-bufsize 4000 --refine-intra 0 --refine-inter 1::RaceHorses_1664x960_30.y4m,--preset slow --no-cutree --ctu 64 --analysis-load x265_analysis_2.dat --analysis-reuse-level 10 --scale-factor 2 --crf 12 --vbv-maxrate 7000 --vbv-bufsize 7000 --refine-intra 2 --refine-inter 2 ElFunete_960x540_60.yuv,--colorprim bt709 --transfer bt709 --chromaloc 2 --aud --repeat-headers --no-opt-qp-pps --no-opt-ref-list-length-pps --wpp --no-interlace --sar 1:1 --min-keyint 60 --no-open-gop --rc-lookahead 180 --bframes 5 --b-intra --ref 4 --cbqpoffs -2 --crqpoffs -2 --lookahead-threads 0 --weightb --qg-size 8 --me star --preset veryslow --frame-threads 1 --b-adapt 2 --aq-mode 3 --rd 6 --pools 15 --colormatrix bt709 --keyint 120 --high-tier --ctu 64 --tune psnr --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500 --analysis-reuse-level 10 --analysis-save elfuente_960x540.dat --scale-factor 2::ElFunete_1920x1080_60.yuv,--colorprim bt709 --transfer bt709 --chromaloc 2 --aud --repeat-headers --no-opt-qp-pps --no-opt-ref-list-length-pps --wpp --no-interlace --sar 1:1 --min-keyint 60 --no-open-gop --rc-lookahead 180 --bframes 5 --b-intra --ref 4 --cbqpoffs -2 --crqpoffs -2 --lookahead-threads 0 --weightb --qg-size 8 --me star --preset veryslow --frame-threads 1 --b-adapt 2 --aq-mode 3 --rd 6 --pools 15 --colormatrix bt709 --keyint 120 --high-tier --ctu 64 --tune psnr --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500 --analysis-reuse-level 10 --analysis-save elfuente_1920x1080.dat --limit-tu 0 --scale-factor 2 --analysis-load elfuente_960x540.dat --refine-intra 4 --refine-inter 2::ElFuente_3840x2160_60.yuv,--colorprim bt709 --transfer bt709 --chromaloc 2 --aud --repeat-headers --no-opt-qp-pps --no-opt-ref-list-length-pps --wpp --no-interlace --sar 1:1 --min-keyint 60 --no-open-gop --rc-lookahead 180 --bframes 5 --b-intra --ref 4 --cbqpoffs -2 --crqpoffs -2 --lookahead-threads 0 --weightb --qg-size 8 --me star --preset veryslow --frame-threads 1 --b-adapt 2 --aq-mode 3 --rd 6 --pools 15 --colormatrix bt709 --keyint 120 --high-tier --ctu 64 --tune=psnr --bitrate 24000 --vbv-bufsize 84000 --vbv-maxrate 49000 --analysis-reuse-level 10 --limit-tu 0 --scale-factor 2 --analysis-load elfuente_1920x1080.dat --refine-intra 4 --refine-inter 2 +#save/load with ctu distortion refinement +CrowdRun_1920x1080_50_10bit_422.yuv,--no-cutree --analysis-save x265_analysis.dat --refine-ctu-distortion 1 --bitrate 7000::--no-cutree --analysis-load x265_analysis.dat --refine-ctu-distortion 1 --bitrate 7000 #segment encoding BasketballDrive_1920x1080_50.y4m, --preset ultrafast --no-open-gop --chunk-start 100 --chunk-end 200
View file
x265_3.0.tar.gz/source/test/save-load-tests.txt
Added
@@ -0,0 +1,19 @@ +# List of command lines to be run by regression tests, see https://bitbucket.org/sborho/test-harness + +# the vast majority of the commands are tested for results matching the +# most recent commit which was known to change outputs. The output +# bitstream must be bit-exact or the test fails. If no golden outputs +# are available the bitstream is validated (decoded) and then saved as a +# new golden output + +# Note: --nr-intra, --nr-inter, and --bitrate (ABR) give different +# outputs for different frame encoder counts. In order for outputs to be +# consistent across many machines, you must force a certain -FN so it is +# not auto-detected. +crowd_run_1080p50.y4m, --preset ultrafast --no-cutree --analysis-save x265_analysis.dat --analysis-reuse-level 1 --scale-factor 2 --crf 26 --vbv-maxrate 8000 --vbv-bufsize 8000::crowd_run_2160p50.y4m, --preset ultrafast --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 1 --scale-factor 2 --crf 26 --vbv-maxrate 12000 --vbv-bufsize 12000 +crowd_run_1080p50.y4m, --preset superfast --no-cutree --analysis-save x265_analysis.dat --analysis-reuse-level 2 --scale-factor 2 --crf 22 --vbv-maxrate 5000 --vbv-bufsize 5000::crowd_run_2160p50.y4m, --preset superfast --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 2 --scale-factor 2 --crf 22 --vbv-maxrate 10000 --vbv-bufsize 10000 +crowd_run_1080p50.y4m, --preset fast --no-cutree --analysis-save x265_analysis.dat --analysis-reuse-level 5 --scale-factor 2 --qp 18::crowd_run_2160p50.y4m, --preset fast --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 5 --scale-factor 2 --qp 18 +crowd_run_1080p50.y4m, --preset medium --no-cutree --analysis-save x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 5000 --vbv-maxrate 5000 --vbv-bufsize 5000 --early-skip --tu-inter-depth 3::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-maxrate 10000 --vbv-bufsize 10000 --early-skip --tu-inter-depth 3 --refine-intra 4 --dynamic-refine::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-load x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-maxrate 10000 --vbv-bufsize 10000 --early-skip --tu-inter-depth 3 --refine-intra 3 --refine-inter 3 +RaceHorses_416x240_30.y4m, --preset slow --no-cutree --ctu 16 --analysis-save x265_analysis.dat --analysis-reuse-level 10 --scale-factor 2 --crf 22 --vbv-maxrate 1000 --vbv-bufsize 1000::RaceHorses_832x480_30.y4m, --preset slow --no-cutree --ctu 32 --analysis-load x265_analysis.dat --analysis-save x265_analysis_2.dat --analysis-reuse-level 10 --scale-factor 2 --crf 16 --vbv-maxrate 4000 --vbv-bufsize 4000 --refine-intra 0 --refine-inter 1::RaceHorses_1664x960_30.y4m, --preset slow --no-cutree --ctu 64 --analysis-load x265_analysis_2.dat --analysis-reuse-level 10 --scale-factor 2 --crf 12 --vbv-maxrate 7000 --vbv-bufsize 7000 --refine-intra 2 --refine-inter 2 +crowd_run_540p50.y4m, --preset veryslow --no-cutree --analysis-save x265_analysis_540.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 5000 --vbv-bufsize 15000 --vbv-maxrate 9000::crowd_run_1080p50.y4m, --preset veryslow --no-cutree --analysis-save x265_analysis_1080.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500::crowd_run_1080p50.y4m, --preset veryslow --no-cutree --analysis-save x265_analysis_1080.dat --analysis-load x265_analysis_540.dat --refine-intra 4 --dynamic-refine --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500::crowd_run_2160p50.y4m, --preset veryslow --no-cutree --analysis-save x265_analysis_2160.dat --analysis-load x265_analysis_1080.dat --refine-intra 3 --dynamic-refine --analysis-reuse-level 10 --scale-factor 2 --bitrate 24000 --vbv-bufsize 84000 --vbv-maxrate 49000::crowd_run_2160p50.y4m, --preset veryslow --no-cutree --analysis-load x265_analysis_2160.dat --refine-intra 2 --dynamic-refine --analysis-reuse-level 10 --scale-factor 1 --bitrate 24000 --vbv-bufsize 84000 --vbv-maxrate 49000 +crowd_run_540p50.y4m, --preset medium --no-cutree --analysis-save x265_analysis_540.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 5000 --vbv-bufsize 15000 --vbv-maxrate 9000::crowd_run_1080p50.y4m, --preset medium --no-cutree --analysis-save x265_analysis_1080.dat --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500::crowd_run_1080p50.y4m, --preset medium --no-cutree --analysis-save x265_analysis_1080.dat --analysis-load x265_analysis_540.dat --refine-intra 4 --dynamic-refine --analysis-reuse-level 10 --scale-factor 2 --bitrate 10000 --vbv-bufsize 30000 --vbv-maxrate 17500::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-save x265_analysis_2160.dat --analysis-load x265_analysis_1080.dat --refine-intra 3 --dynamic-refine --analysis-reuse-level 10 --scale-factor 2 --bitrate 24000 --vbv-bufsize 84000 --vbv-maxrate 49000::crowd_run_2160p50.y4m, --preset medium --no-cutree --analysis-load x265_analysis_2160.dat --refine-intra 2 --dynamic-refine --analysis-reuse-level 10 --scale-factor 1 --bitrate 24000 --vbv-bufsize 84000 --vbv-maxrate 49000
View file
x265_2.9.tar.gz/source/test/smoke-tests.txt -> x265_3.0.tar.gz/source/test/smoke-tests.txt
Changed
@@ -22,3 +22,4 @@ CrowdRun_1920x1080_50_10bit_444.yuv,--preset=superfast --bitrate 7000 --sao --limit-sao # Main12 intraCost overflow bug test 720p50_parkrun_ter.y4m,--preset medium +720p50_parkrun_ter.y4m,--preset=fast --hevc-aq --no-cutree
View file
x265_2.9.tar.gz/source/test/testharness.h -> x265_3.0.tar.gz/source/test/testharness.h
Changed
@@ -93,9 +93,9 @@ #define BENCH_RUNS 2000 -// Adapted from checkasm.c, runs each optimized primitive four times, measures rdtsc -// and discards invalid times. Repeats 1000 times to get a good average. Then measures -// the C reference with fewer runs and reports X factor and average cycles. +/* Adapted from checkasm.c, runs each optimized primitive four times, measures rdtsc + * and discards invalid times. Repeats BENCH_RUNS times to get a good average. + * Then measures the C reference with BENCH_RUNS / 4 runs and reports X factor and average cycles.*/ #define REPORT_SPEEDUP(RUNOPT, RUNREF, ...) \ { \ uint32_t cycles = 0; int runs = 0; \
View file
x265_2.9.tar.gz/source/x265.cpp -> x265_3.0.tar.gz/source/x265.cpp
Changed
@@ -65,6 +65,8 @@ { b_ctrl_c = 1; } +#define START_CODE 0x00000001 +#define START_CODE_BYTES 4 struct CLIOptions { @@ -72,6 +74,8 @@ ReconFile* recon; OutputFile* output; FILE* qpfile; + FILE* zoneFile; + FILE* dolbyVisionRpu; /* File containing Dolby Vision BL RPU metadata */ const char* reconPlayCmd; const x265_api* api; x265_param* param; @@ -94,6 +98,8 @@ recon = NULL; output = NULL; qpfile = NULL; + zoneFile = NULL; + dolbyVisionRpu = NULL; reconPlayCmd = NULL; api = NULL; param = NULL; @@ -110,7 +116,9 @@ void destroy(); void printStatus(uint32_t frameNum); bool parse(int argc, char **argv); + bool parseZoneParam(int argc, char **argv, x265_param* globalParam, int zonefileCount); bool parseQPFile(x265_picture &pic_org); + bool parseZoneFile(); }; void CLIOptions::destroy() @@ -124,6 +132,12 @@ if (qpfile) fclose(qpfile); qpfile = NULL; + if (zoneFile) + fclose(zoneFile); + zoneFile = NULL; + if (dolbyVisionRpu) + fclose(dolbyVisionRpu); + dolbyVisionRpu = NULL; if (output) output->release(); output = NULL; @@ -156,6 +170,110 @@ prevUpdateTime = time; } +bool CLIOptions::parseZoneParam(int argc, char **argv, x265_param* globalParam, int zonefileCount) +{ + bool bError = false; + int bShowHelp = false; + int outputBitDepth = 0; + const char *profile = NULL; + + /* Presets are applied before all other options. */ + for (optind = 0;;) + { + int c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) + break; + else if (c == 'D') + outputBitDepth = atoi(optarg); + else if (c == 'P') + profile = optarg; + else if (c == '?') + bShowHelp = true; + } + + if (!outputBitDepth && profile) + { + /* try to derive the output bit depth from the requested profile */ + if (strstr(profile, "10")) + outputBitDepth = 10; + else if (strstr(profile, "12")) + outputBitDepth = 12; + else + outputBitDepth = 8; + } + + api = x265_api_get(outputBitDepth); + if (!api) + { + x265_log(NULL, X265_LOG_WARNING, "falling back to default bit-depth\n"); + api = x265_api_get(0); + } + + if (bShowHelp) + { + printVersion(globalParam, api); + showHelp(globalParam); + } + + globalParam->rc.zones[zonefileCount].zoneParam = api->param_alloc(); + if (!globalParam->rc.zones[zonefileCount].zoneParam) + { + x265_log(NULL, X265_LOG_ERROR, "param alloc failed\n"); + return true; + } + + memcpy(globalParam->rc.zones[zonefileCount].zoneParam, globalParam, sizeof(x265_param)); + + for (optind = 0;;) + { + int long_options_index = -1; + int c = getopt_long(argc, argv, short_options, long_options, &long_options_index); + if (c == -1) + break; + + if (long_options_index < 0 && c > 0) + { + for (size_t i = 0; i < sizeof(long_options) / sizeof(long_options[0]); i++) + { + if (long_options[i].val == c) + { + long_options_index = (int)i; + break; + } + } + + if (long_options_index < 0) + { + /* getopt_long might have already printed an error message */ + if (c != 63) + x265_log(NULL, X265_LOG_WARNING, "internal error: short option '%c' has no long option\n", c); + return true; + } + } + if (long_options_index < 0) + { + x265_log(NULL, X265_LOG_WARNING, "short option '%c' unrecognized\n", c); + return true; + } + + bError |= !!api->zone_param_parse(globalParam->rc.zones[zonefileCount].zoneParam, long_options[long_options_index].name, optarg); + + if (bError) + { + const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind - 2]; + x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s = %s\n", name, optarg); + return true; + } + } + + if (optind < argc) + { + x265_log(param, X265_LOG_WARNING, "extra unused command arguments given <%s>\n", argv[optind]); + return true; + } + return false; +} + bool CLIOptions::parse(int argc, char **argv) { bool bError = false; @@ -311,6 +429,21 @@ if (!this->qpfile) x265_log_file(param, X265_LOG_ERROR, "%s qpfile not found or error in opening qp file\n", optarg); } + OPT("dolby-vision-rpu") + { + this->dolbyVisionRpu = x265_fopen(optarg, "rb"); + if (!this->dolbyVisionRpu) + { + x265_log_file(param, X265_LOG_ERROR, "Dolby Vision RPU metadata file %s not found or error in opening file\n", optarg); + return true; + } + } + OPT("zonefile") + { + this->zoneFile = x265_fopen(optarg, "rb"); + if (!this->zoneFile) + x265_log_file(param, X265_LOG_ERROR, "%s zone file not found or error in opening zone file\n", optarg); + } OPT("fullhelp") { param->logLevel = X265_LOG_FULL; @@ -519,6 +652,59 @@ return 1; } +bool CLIOptions::parseZoneFile() +{ + char line[256]; + char* argLine; + param->rc.zonefileCount = 0; + + while (fgets(line, sizeof(line), zoneFile)) + { + if (!((*line == '#') || (strcmp(line, "\r\n") == 0))) + param->rc.zonefileCount++; + } + + rewind(zoneFile); + param->rc.zones = X265_MALLOC(x265_zone, param->rc.zonefileCount); + for (int i = 0; i < param->rc.zonefileCount; i++) + { + while (fgets(line, sizeof(line), zoneFile)) + { + if (*line == '#' || (strcmp(line, "\r\n") == 0)) + continue; + param->rc.zones[i].zoneParam = X265_MALLOC(x265_param, 1); + int index = (int)strcspn(line, "\r\n"); + line[index] = '\0'; + argLine = line; + while (isspace((unsigned char)*argLine)) argLine++; + char* start = strchr(argLine, ' '); + start++; + param->rc.zones[i].startFrame = atoi(argLine); + int argCount = 0; + char **args = (char**)malloc(256 * sizeof(char *)); + // Adding a dummy string to avoid file parsing error + args[argCount++] = (char *)"x265"; + char* token = strtok(start, " "); + while (token) + { + args[argCount++] = token; + token = strtok(NULL, " "); + } + args[argCount] = NULL; + CLIOptions cliopt; + if (cliopt.parseZoneParam(argCount, args,param, i)) + { + cliopt.destroy(); + if (cliopt.api) + cliopt.api->param_free(cliopt.param); + exit(1); + } + break; + } + } + return 1; +} + #ifdef _WIN32 /* Copy of x264 code, which allows for Unicode characters in the command line. * Retrieve command line arguments as UTF-8. */ @@ -552,6 +738,59 @@ } #endif +/* 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; +} + + /* CLI return codes: * * 0 - encode successful @@ -598,6 +837,16 @@ if (cliopt.reconPlayCmd) reconPlay = new ReconPlay(cliopt.reconPlayCmd, *param); + if (cliopt.zoneFile) + { + if (!cliopt.parseZoneFile()) + { + x265_log(NULL, X265_LOG_ERROR, "Unable to parse zonefile\n"); + fclose(cliopt.zoneFile); + 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 */ @@ -630,8 +879,10 @@ x265_stats stats; uint32_t nal; int16_t *errorBuf = NULL; + bool bDolbyVisionRPU = false; int ret = 0; + if (!param->bRepeatHeaders) { if (api->encoder_headers(encoder, &p_nal, &nal) < 0) @@ -646,6 +897,13 @@ api->picture_init(param, pic_in); + if (param->dolbyProfile && cliopt.dolbyVisionRpu) + { + pic_in->rpu.payload = X265_MALLOC(uint8_t, 1024); + if (pic_in->rpu.payload) + bDolbyVisionRPU = true; + } + if (cliopt.bDither) { errorBuf = X265_MALLOC(int16_t, param->sourceWidth + 1); @@ -685,8 +943,13 @@ } /* Overwrite PTS */ pic_in->pts = pic_in->poc; - } + if (bDolbyVisionRPU) + { + if (rpuParser(pic_in, cliopt.dolbyVisionRpu) > 0) + goto fail; + } + } int numEncoded = api->encoder_encode(encoder, &p_nal, &nal, pic_in, pic_recon); if (numEncoded < 0) { @@ -749,6 +1012,13 @@ break; } + if (bDolbyVisionRPU) + { + if(fgetc(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 (cliopt.bProgress) fprintf(stderr, "%*s\r", 80, " ");
View file
x265_2.9.tar.gz/source/x265.h -> x265_3.0.tar.gz/source/x265.h
Changed
@@ -81,6 +81,7 @@ NAL_UNIT_FILLER_DATA, NAL_UNIT_PREFIX_SEI, NAL_UNIT_SUFFIX_SEI, + NAL_UNIT_UNSPECIFIED = 62, NAL_UNIT_INVALID = 64, } NalUnitType; @@ -129,6 +130,8 @@ int lookaheadDepth; int chunkStart; int chunkEnd; + int cuTree; + int ctuDistortionRefine; }x265_analysis_validate; /* Stores intra analysis data for a single frame. This struct needs better packing */ @@ -138,6 +141,7 @@ uint8_t* modes; char* partSizes; uint8_t* chromaModes; + int8_t* cuQPOff; }x265_analysis_intra_data; typedef struct x265_analysis_MV @@ -162,6 +166,7 @@ int8_t* refIdx[2]; x265_analysis_MV* mv[2]; int64_t* sadCost; + int8_t* cuQPOff; }x265_analysis_inter_data; typedef struct x265_weight_param @@ -178,9 +183,12 @@ typedef uint64_t sse_t; #endif +#define CTU_DISTORTION_OFF 0 +#define CTU_DISTORTION_INTERNAL 1 +#define CTU_DISTORTION_EXTERNAL 2 + typedef struct x265_analysis_distortion_data { - sse_t* distortion; sse_t* ctuDistortion; double* scaledDistortion; double averageDistortion; @@ -189,6 +197,7 @@ uint32_t lowDistortionCtuCount; double* offset; double* threshold; + }x265_analysis_distortion_data; /* Stores all analysis data for a single frame */ @@ -308,7 +317,8 @@ { NO_INFO = 0, AVC_INFO = 1, -}MVRefineType; + HEVC_INFO = 2, +}AnalysisRefineType; /* Arbitrary User SEI * Payload size is in bytes and the payload pointer must be non-NULL. @@ -360,6 +370,12 @@ x265_sei_payload *payloads; } x265_sei; +typedef struct x265_dolby_vision_rpu +{ + int payloadSize; + uint8_t* payload; +}x265_dolby_vision_rpu; + /* Used to pass pictures into the encoder, and to get picture data back out of * the encoder. The input and output semantics are different */ typedef struct x265_picture @@ -445,6 +461,9 @@ // pts is reordered in the order of encoding. int64_t reorderedPts; + + //Dolby Vision RPU metadata + x265_dolby_vision_rpu rpu; } x265_picture; typedef enum @@ -641,6 +660,8 @@ static const char * const x265_interlace_names[] = { "prog", "tff", "bff", 0 }; static const char * const x265_analysis_names[] = { "off", "save", "load", 0 }; +struct x265_zone; +struct x265_param; /* Zones: override ratecontrol for specific sections of the video. * If zones overlap, whichever comes later in the list takes precedence. */ typedef struct x265_zone @@ -649,6 +670,7 @@ int bForceQp; /* whether to use qp vs bitrate factor */ int qp; float bitrateFactor; + struct x265_param* zoneParam; } x265_zone; /* data to calculate aggregate VMAF score */ @@ -688,9 +710,12 @@ int ssim; int ms_ssim; char *pool; + int thread; + int subsample; + int enable_conf_interval; }x265_vmaf_commondata; -static const x265_vmaf_commondata vcd[] = { { NULL, (char *)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0, 0, NULL } }; +static const x265_vmaf_commondata vcd[] = { { NULL, (char *)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 1, 0 } }; /* x265 input parameters * @@ -1320,13 +1345,25 @@ /* Enable adaptive quantization. This mode distributes available bits between all * CTUs of a frame, assigning more bits to low complexity areas. Turning * this ON will usually affect PSNR negatively, however SSIM and visual quality - * generally improves. Default: X265_AQ_VARIANCE */ + * generally improves. Default: X265_AQ_AUTO_VARIANCE */ int aqMode; + /* + * Enable adaptive quantization. + * It scales the quantization step size according to the spatial activity of one + * coding unit relative to frame average spatial activity. This AQ method utilizes + * the minimum variance of sub-unit in each coding unit to represent the coding + * unit’s spatial complexity. */ + int hevcAq; + /* Sets the strength of AQ bias towards low detail CTUs. Valid only if * AQ is enabled. Default value: 1.0. Acceptable values between 0.0 and 3.0 */ double aqStrength; + /* Delta QP range by QP adaptation based on a psycho-visual model. + * Acceptable values between 1.0 to 6.0 */ + double qpAdaptationRange; + /* Sets the maximum rate the VBV buffer should be assumed to refill at * Default is zero */ int vbvMaxBitrate; @@ -1374,6 +1411,9 @@ int zoneCount; x265_zone* zones; + /* number of zones in zone-file*/ + int zonefileCount; + /* specify a text file which contains MAX_MAX_QP + 1 floating point * values to be copied into x265_lambda_tab and a second set of * MAX_MAX_QP + 1 floating point values for x265_lambda2_tab. All values @@ -1662,7 +1702,7 @@ double vbvEndFrameAdjust; /* Reuse MV information obtained through API */ - int bMVType; + int bAnalysisType; /* Allow the encoder to have a copy of the planes of x265_picture in Frame */ int bCopyPicToFrame; @@ -1710,8 +1750,22 @@ /* File containing base64 encoded SEI messages in POC order */ const char* naluFile; -} x265_param; + /* Generate bitstreams confirming to the specified dolby vision profile, + * note that 0x7C01 makes RPU appear to be an unspecified NAL type in + * HEVC stream. if BL is backward compatible, Dolby Vision single + * layer VES will be equivalent to a backward compatible BL VES on legacy + * device as RPU will be ignored. Default 0 (disabled) */ + int dolbyProfile; + + /* Set concantenation flag for the first keyframe in the HRD buffering period SEI. */ + int bEnableHRDConcatFlag; + + /* Store/normalize ctu distortion in analysis-save/load. Ranges from 0 - 1. + * 0 - Disabled. 1 - Save/Load ctu distortion to/from the file specified + * analysis-save/load. Default 0. */ + int ctuDistortionRefine; +} x265_param; /* x265_param_alloc: * Allocates an x265_param instance. The returned param structure is not * special in any way, but using this method together with x265_param_free() @@ -1738,6 +1792,8 @@ #define X265_PARAM_BAD_VALUE (-2) int x265_param_parse(x265_param *p, const char *name, const char *value); +int x265_zone_param_parse(x265_param* p, const char* name, const char* value); + static const char * const x265_profile_names[] = { /* HEVC v1 */ "main", "main10", "mainstillpicture", /* alias */ "msp", @@ -2031,6 +2087,7 @@ double (*calculate_vmaf_framelevelscore)(x265_vmaf_framedata *); void (*vmaf_encoder_log)(x265_encoder*, int, char**, x265_param *, x265_vmaf_data *); #endif + int (*zone_param_parse)(x265_param*, const char*, const char*); /* add new pointers to the end, or increment X265_MAJOR_VERSION */ } x265_api;
View file
x265_2.9.tar.gz/source/x265cli.h -> x265_3.0.tar.gz/source/x265cli.h
Changed
@@ -242,6 +242,7 @@ { "no-info", no_argument, NULL, 0 }, { "zones", required_argument, NULL, 0 }, { "qpfile", required_argument, NULL, 0 }, + { "zonefile", required_argument, NULL, 0 }, { "lambda-file", required_argument, NULL, 0 }, { "b-intra", no_argument, NULL, 0 }, { "no-b-intra", no_argument, NULL, 0 }, @@ -288,13 +289,15 @@ { "dhdr10-info", required_argument, NULL, 0 }, { "dhdr10-opt", no_argument, NULL, 0}, { "no-dhdr10-opt", no_argument, NULL, 0}, + { "dolby-vision-profile", required_argument, NULL, 0 }, { "refine-mv", no_argument, NULL, 0 }, { "no-refine-mv", no_argument, NULL, 0 }, + { "refine-ctu-distortion", required_argument, NULL, 0 }, { "force-flush", required_argument, NULL, 0 }, { "splitrd-skip", no_argument, NULL, 0 }, { "no-splitrd-skip", no_argument, NULL, 0 }, { "lowpass-dct", no_argument, NULL, 0 }, - { "refine-mv-type", required_argument, NULL, 0 }, + { "refine-analysis-type", required_argument, NULL, 0 }, { "copy-pic", no_argument, NULL, 0 }, { "no-copy-pic", no_argument, NULL, 0 }, { "max-ausize-factor", required_argument, NULL, 0 }, @@ -305,6 +308,12 @@ { "atc-sei", required_argument, NULL, 0 }, { "pic-struct", required_argument, NULL, 0 }, { "nalu-file", required_argument, NULL, 0 }, + { "dolby-vision-rpu", required_argument, NULL, 0 }, + { "hrd-concat", no_argument, NULL, 0}, + { "no-hrd-concat", no_argument, NULL, 0 }, + { "hevc-aq", no_argument, NULL, 0 }, + { "no-hevc-aq", no_argument, NULL, 0 }, + { "qp-adaptation-range", required_argument, NULL, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, @@ -355,6 +364,9 @@ H0(" --dhdr10-info <filename> JSON file containing the Creative Intent Metadata to be encoded as Dynamic Tone Mapping\n"); H0(" --[no-]dhdr10-opt Insert tone mapping SEI only for IDR frames and when the tone mapping information changes. Default disabled\n"); #endif + H0(" --dolby-vision-profile <float|integer> Specifies Dolby Vision profile ID. Currently only profile 5, profile 8.1 and profile 8.2 enabled. Specified as '5' or '50'. Default 0 (disabled).\n"); + H0(" --dolby-vision-rpu <filename> File containing Dolby Vision RPU metadata.\n" + " If given, x265's Dolby Vision metadata parser will fill the RPU field of input pictures with the metadata read from the file. Default NULL(disabled).\n"); H0(" --nalu-file <filename> Text file containing SEI messages in the following format : <POC><space><PREFIX><space><NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload>\n"); H0("-f/--frames <integer> Maximum number of frames to encode. Default all\n"); H0(" --seek <integer> First frame to encode\n"); @@ -458,6 +470,7 @@ H1(" 0 - flush the encoder only when all the input pictures are over.\n"); H1(" 1 - flush all the frames even when the input is not over. Slicetype decision may change with this option.\n"); H1(" 2 - flush the slicetype decided frames only.\n"); + H0(" --[no-]-hrd-concat Set HRD concatenation flag for the first keyframe in the buffering period SEI. Default %s\n", OPT(param->bEnableHRDConcatFlag)); H0("\nRate control, Adaptive Quantization:\n"); H0(" --bitrate <integer> Target bitrate (kbps) for ABR (implied). Default %d\n", param->rc.bitrate); H1("-q/--qp <integer> QP for P slices in CQP mode (implied). --ipratio and --pbration determine other slice QPs\n"); @@ -488,7 +501,7 @@ H0(" --analysis-load <filename> Load analysis buffers from the file specified. Default Disabled\n"); H0(" --analysis-reuse-file <filename> Specify file name used for either dumping or reading analysis data. Deault x265_analysis.dat\n"); H0(" --analysis-reuse-level <1..10> Level of analysis reuse indicates amount of info stored/reused in save/load mode, 1:least..10:most. Default %d\n", param->analysisReuseLevel); - H0(" --refine-mv-type <string> Reuse MV information received through API call. Supported option is avc. Default disabled - %d\n", param->bMVType); + H0(" --refine-analysis-type <string> Reuse anlaysis information received through API call. Supported options are avc and hevc. Default disabled - %d\n", param->bAnalysisType); H0(" --scale-factor <int> Specify factor by which input video is scaled down for analysis save mode. Default %d\n", param->scaleFactor); H0(" --refine-intra <0..4> Enable intra refinement for encode that uses analysis-load.\n" " - 0 : Forces both mode and depth from the save encode.\n" @@ -506,8 +519,14 @@ " Default:%d\n", param->interRefine); H0(" --[no-]dynamic-refine Dynamically changes refine-inter level for each CU. Default %s\n", OPT(param->bDynamicRefine)); H0(" --[no-]refine-mv Enable mv refinement for load mode. Default %s\n", OPT(param->mvRefine)); + H0(" --refine-ctu-distortion Store/normalize ctu distortion in analysis-save/load.\n" + " - 0 : Disabled.\n" + " - 1 : Store/Load ctu distortion to/from the file specified in analysis-save/load.\n" + " Default 0 - Disabled\n"); H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes. Default %d\n", param->rc.aqMode); + H0(" --[no-]hevc-aq Mode for HEVC Adaptive Quantization. Default %s\n", OPT(param->rc.hevcAq)); H0(" --aq-strength <float> Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength); + H0(" --qp-adaptation-range <float> Delta QP range by QP adaptation based on a psycho-visual model (1.0 to 6.0). Default %.2f\n", param->rc.qpAdaptationRange); H0(" --[no-]aq-motion Adaptive Quantization based on the relative motion of each CU w.r.t., frame. Default %s\n", OPT(param->bOptCUDeltaQP)); H0(" --qg-size <int> Specifies the size of the quantization group (64, 32, 16, 8). Default %d\n", param->rc.qgSize); H0(" --[no-]cutree Enable cutree for Adaptive Quantization. Default %s\n", OPT(param->rc.cuTree)); @@ -528,6 +547,7 @@ H1(" where <option> is either\n"); H1(" q=<integer> (force QP)\n"); H1(" or b=<float> (bitrate multiplier)\n"); + H0(" --zonefile <filename> Zone file containing the zone boundaries and the parameters to be reconfigured.\n"); H1(" --lambda-file <string> Specify a file containing replacement values for the lambda tables\n"); H1(" MAX_MAX_QP+1 floats for lambda table, then again for lambda2 table\n"); H1(" Blank lines and lines starting with hash(#) are ignored\n");
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.